reCaptcha is now difficult to read (decipher actually). So I am looking for an alternative captcha system to use.
I am thinking of using a simple Math based system, for example : "What is 2+5".
Are there any such plugins, or, ideas on how to build my own?
(Not complicated math like this one)
PHP - Generates a simple addition or subtraction math question, randomly alternating between displaying numbers (10 - 3) and words (seven plus five) and accepts answers numerically (14) or as words (fourteen). Returns an array representing the components of the equation
[0] - first variable value, as string, like either '4' or 'four'
[1] - second value, the operator, like '+' or 'plus'
[2] - third value, the second variable, like 'ten' or '10'
[3] - the answer, in numerical form, like '14'
[4] - the answer, in text form, like 'fourteen'
So just print the equation to the page, store the array in $_SESSION, and then check the answer the user provides.
<?php
// array of numbers and their corresponding word versions
// you can simply do $wordNumbers[6] and get 'six'
$wordNumbers = array(
0 => 'zero',
1 => 'one',
2 => 'two',
3 => 'three',
4 => 'four',
5 => 'five',
6 => 'six',
7 => 'seven',
8 => 'eight',
9 => 'nine',
10 => 'ten',
11 => 'eleven',
12 => 'twelve',
13 => 'thirteen',
14 => 'fourteen',
15 => 'fifteen',
16 => 'sixteen',
17 => 'seventeen',
18 => 'eighteen',
19 => 'nineteen',
20 => 'twenty'
);
/*
*
* returns an array representing components of a math captcha
* [0] - first variable value, as string, like either '4' or 'four'
* [1] - second value, the operator, like '+' or 'plus'
* [2] - third value, the second variable, like 'ten' or '10'
* [3] - the answer, in numerical form, like '14'
* [4] - the answer, in text form, like 'fourteen'
*/
function getMathCaptcha(){
global $wordNumbers;
$equation = array();
// get first number, between 7 and 13 inclusive
$n1 = rand(7, 13);
$r = rand(0,1);
// return $n1 as digit or text
if ($r == 0) {
$equation[0] = $n1;
} else {
$equation[0] = $wordNumbers[$n1];
}
// get operator
$o = rand(0,1);
$r = rand(0,1);
if ($o == 0){
// subtraction
if ($r == 0) {
$equation[1] = '-';
} else {
$equation[1] = 'minus';
}
} else {
// addition
if ($r == 0) {
$equation[1] = '+';
} else {
$equation[1] = 'plus';
}
}
// get second number, between 0 and 7 inclusive, so no negative answers
$n2 = rand(1,7);
$r = rand(0,1);
// return $n2 as digit or text
if ($r == 0) {
$equation[2] = $n2;
} else {
$equation[2] = $wordNumbers[$n2];
}
// get answer
if ($o == 0){
$answer = $n1 - $n2;
} else {
$answer = $n1 + $n2;
}
// answer as digit and text
$equation[3] = $answer;
$equation[4] = $wordNumbers[$answer];
return $equation;
}
?>
have you tried a captcha method like mine below?
what are the downpoints of this captcha method
or are you specifically wanting to use a user-entry method?
How about using Captchator?
It's easy to implement and it just works! There are also code samples for PHP and Ruby out there, shouldn't be difficult to implement in other languages.
Math based captchas are weak and easy to pass, there are many spambots out there that know how to do the math :)
If I were to make a simple one, it would go along the lines of:
Make different items of categories, such as flowers, fruits, vegetables, and meats. Then design the captcha to ask for a total of a category.
For example:
Randomize the categories, choose 2 unique ones. So perhaps we got flowers and fruits.Next, ask the user: "If you have 3 roses, 4 oranges, and 6 apples, then how many fruits do you have?"
Simple pattern:
Get n-1 unique categories. Show n items, where each item belongs to one of the unique categories. Ask for a total from one category.
you can create a captcha like this on your own. All you have to do is create a function which will pick up a random number between the given list of numbers and call the function twice to pick up two random numbers.
Store the result in a session variable or any other variable so that you can verify it later.
below is an example coded in c#
Random a=new Random();
a.Next();//it will return you a non negative number
a.Next(min value,maximum value);//it will return you a number between the range specified.
Hope this helps
Related
I have a table with two columns, X and Y and data something like:
X Y
1 1
1 2
1 3
1 4
2 5
2 6
And when I do something like ->pluck('Y', 'X') I want an answer like:
['1' => [1,2,3,4], '2' => [5,6]]
But instead it just gives me one value instead of an array like
['1' => 1, '2' => '5']
How can I make the values an array?
Using reduce
$collection->reduce(function ($carry, $item) {
// First iteration
if ($carry == null) {
$carry = [];
}
$carry[$item->X][] = $item->Y;
return $carry;
});
Using groupBy:
$collection->groupBy('X')->map(function ($item) {
return $item->pluck('Y');
})->toArray()
Using mapToGroups
$collection->mapToGroups(function ($item) {
return [$item['X'] => $item['Y']];
})->toArray()
I have an array that plucks values to an array like so:
/* Pluck just the wattage values to an array */
$realtime_data_array = $latestrtfeed->nth(60)->reverse()->pluck('data')->toArray();
which results in:
array:150 [▼
0 => 20277.6
1 => 20281.4
2 => 20285.3
3 => 20289.7
4 => 20293.8
5 => 20298.6
6 => 20303.2
7 => 20307.4
8 => 20311.5
9 => 20315.8
10 => 20319.8
these value get inputted to the chart like so:
$realtime_consumption_chart->dataset('kWh', 'line', $realtime_data_array);
The problem is that the sensor is storing cumulative values and I only want to show the difference between value 0 and value 1 then difference between value 1 and value 2 and so on and so on.
How would I go about something like that?
I am going to take a shot and say that I'm going to have to do a FOREACH on the array and create a new array with the values adjusted, but how do I go about that? maybe:
foreach ($realtime_data_array as $data) {
$realtime_data_array_corrected = ($data[1]-$data[0])->toArray();
}
Nope there is something I'm doing wrong or not considering here.
for ($i = 0; $i < sizeof($realtime_data_array); $i++) {
if($i==0) {
$realtime_data_array_corrected[$i] = 0;
continue;
}
$realtime_data_array_corrected[$i] = $realtime_data_array[$i] - $realtime_data_array[$i-1];
}
The order I would like the end result to appear in is Exact Matches first given a input string, followed by other matches that are Contains for a given field. I tried to approach this in a very rudimentary way as shown here in this example:
var raw = Model.SearchResults.Where(m => m.EffectiveDateTime != null).OrderBy(m => m.EffectiveDateTime).ToList();
var exact = raw.Where(m => m.IssueNumber.ToLower() == Model.SearchText.ToLower());
var contains = raw.Where(m => m.IssueNumber.ToLower().Contains(Model.SearchText.ToLower()));
var list = exact.Union(contains);
This approach seems like it'd be a really bad way to do this. In fact, the Union portion seems to effectively crash my application. Is there an opposite to Intersection which would give me the remaining results outside the Exact matches that I could then append to a final list so that the order would be Exact Matches followed by StartsWith matches followed finally by Contains matches in that descending order?
To answer your original question, you can use a temporary expression to classify the match types, then order by the match type and other criteria, and it will translate to SQL as well:
var st = Model.SearchText.ToLower();
var list = Model.SearchResults.Where(m => m.EffectiveDateTime != null)
.Select(m => new {
m,
im = m.IssueNumber.ToLower()
})
.Select(mim => new {
mim.m,
Rank = mim.im == st ? 1 : mim.im.StartsWith(st) ? 2 : mim.im.Contains(st) ? 3 : 4
})
.Where(mr => mr.Rank < 4)
.OrderBy(mr => mr.Rank)
.ThenBy(mr => mr.m.EffectiveDateTime)
.Select(mr => mr.m)
.ToList();
I did the double Select to emulate let from fluent syntax, which I think is a bit clearer than lambda syntax in this case:
var lisx = (from m in Model.SearchResults
where m.EffectiveDateTime != null
let im = m.IssueNumber.ToLower()
let Rank = im == st ? 1 : im.StartsWith(st) ? 2 : im.Contains(st) ? 3 : 4
where Rank < 4
orderby Rank, m.EffectiveDateTime
select m)
.ToList();
Also, if you do the whole query in the database, the ToLower is likely unnecessary, as the default for SQL is probably to be case-insensitive anyway.
Actually, I went back to the drawing board and figured it out. This is a little bit better for me and returns the results I needed.
var list = Model.SearchResults
.Where(e => e.A.ToLower().Contains(Model.SearchText.ToLower()))
.GroupBy(d => new { d.A, d.B, d.C})
.OrderBy(x => x.Key.A)
.ThenBy(x => x.Key.B)
.ThenBy(x => x.Key.C)
.Select(x => new
{
A= x.Key.A,
B= x.Key.B,
C= x.Key.C
})
.ToList();
I am trying to write session in controller. My structure is
$_SESSION['a'][0] = 1;
$_SESSION['a'][1] = 2;
$_SESSION['a'][2] = 3;
And I am trying this
Configure::write('Session', ['a' =>'1'])
But it is not working. How do this in cakephp 3 way
To write variable in Session in CakePHP 3 you need to write following code :
$this->request->session()->write('Your Key',Your_array);
To know more information you can visit here :
http://book.cakephp.org/3.0/en/development/sessions.html
To make things perfectly clear:
// code writing array to session
$a = [ "abc" => "word", "123" => 42, "?" => $b ];
$a["more"] = "if you need to add";
$a[] = "whatever";
$this->request->session()->write( 'my_array', $a );
// code reading array from session
$recall = $this->request->session()->read( 'my_array' );
debug( sprintf( "What's the word? [%s]", $recall["abc"] ) );
You can simply use
$session->write([
'key1' => 'blue',
'key2' => 'green',
]);
I am refering to
http://book.cakephp.org/3.0/en/development/sessions.html#reading-writing-session-data
The answer is that this cannot be done in CakePHP 3.x
In vanilla PHP, it's possible to do this:
<?php
session_start();
$_SESSION['a'][0] = 1;
$_SESSION['a'][1] = 2;
$_SESSION['a'][2] = 3;
var_dump($_SESSION);
?>
Which will output:
array(1) {
["a"]=> array(3) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
}
}
This is correct, and what should happen.
In CakePHP, you cannot specify arrays in the session key. For example:
$this->request->session()->write('a[]', 1);
$this->request->session()->write('a[]', 2);
$this->request->session()->write('a[]', 3);
Will not work.
If you remove the [] the value will get overwritten. For example:
$this->request->session()->write('a', 1);
$this->request->session()->write('a', 2);
$this->request->session()->write('a', 3);
The value of $this->request->session()->read('a') would be 3. The values 1 and 2 have been overwritten. Again, this is to be expected because you're overwriting the key a each time. The equivalent vanilla PHP for this is:
$_SESSION['a'] = 1;
$_SESSION['a'] = 2;
$_SESSION['a'] = 3;
Due to the lack of an indexed array, $_SESSION['a'] gets overwritten each time. This is normal behaviour. It needs to have the indexes (e.g. ['a'][0], ['a'][1], ...) to work!
The other answers where they have given things like key1 and key2 are not appropriate. Because there are many situations where you want everything contained within an indexed array. Generating separate key names is wrong for this type of scenario.
My edit of the accepted answer was rejected, so I present the - seemingly necessary - explicit code example, for the benefit of #Andy and others.
// code to write to session
$a = [ 0 => "zero", 1 => "one", 2 => "two" ];
$a[] = "three";
$this->request->session()->write( 'my_array', $a );
// code to read from session
$z = $this->request->session()->read( 'my_array' );
debug( $a[3] ); // outputs "three"
Please explain this Ruby code so I can convert it to PHP:
data = Hash.new({})
mysql_results.each { |r| data[r['year']][r['week']] = r['count'] }
(year_low..year_high).each do |year|
(1..52).each do |week|
puts "#{year} #{week} #{data[year][week]}"
end
end
data = Hash.new({})
# create hash 'data'
mysql_results.each { |r| data[r['year']][r['week']] = r['count'] }
# maps each row from sql query to hash like this: data[2010][30] = 23
# So you can access 'count' from every year and week in very simple way
(year_low..year_high).each do |year|
# for (year = year_low; year <= year_high; year++)
(1..52).each do |week|
# for (week = 1; week <=52; week++)
puts "#{year} #{week} #{data[year][week]}"
# printf("%d %d %d\n", year, week, data[year][week]);
end
end
Sorry for mixing C with pseudo code, but I hope it helps!
The first bit is just forming an array like so:
$data[2009][17] = 10;
PHP equivalent of that would be:
foreach ($mysql_results as $r){
$data[$r['year']][$r['week']] = $r['count'];
}
The second part would equate to the following:
foreach(range($year_low, $year_high) as $year){
foreach(range(1, 52) as $week){
print $year.' '.$week.' '.$data[$year][$week]
}
}
Hope that helps :)
$data = array();
#Build an array of 'count' per year/week
foreach($mysql_results as $r) {
$data[$r['year']][$r['week']] = $r['count'];
}
#Loop through the $data variable, printing out the 'count' for each year in the array,
#and all 52 weeks that year
for($year = $year_min; $year <= $year_max; $year++) {
for($week=1; $week<=52; $week++) {
echo "$year $week {$data[$year][$week]}";
}
}
Note that year_low and year_high are variables undefined in the current snippet, but they should be known to you.
Also, $mysql_results should be an array containing all rows returned by the database.
In short, the following code does this:
Make an array grouped per year, then per week, containing the value 'count'
Loop through this array, displaying, in order, the year, the week, and the value for 'count', if any