I need to validate a field in my form, this field belongs to the personal identification number of my country, this number has 10 digits
Example: card = 1710034065
2 1 2 1 2 1 2 1 2 (coefficient)
1 7 1 0 0 3 4 0 6 (personal identification number)
2 7 2 0 0 3 8 0 12 = 25 (Multiply each digit of the personal number by the
3 coefficient, if the result > 10 add between digits).
add multiplications
The result of the sum
25/10 = 2, Residue 5, divide 10 - residue 5 = 5 (check digit) ** which equals the last number of identity number**
Now I need is to implement this logic in the framework and I have no idea how,
I have a example code in java to get a better idea of what I need to do.
function check_cedula( form )
{
var cedula = form.cedula.value;
array = cedula.split( "" );
num = array.length;
if ( num == 10 )
{
total = 0;
digito = (array[9]*1);
for( i=0; i < (num-1); i++ )
{
mult = 0;
if ( ( i%2 ) != 0 ) {
total = total + ( array[i] * 1 );
}
else
{
mult = array[i] * 2;
if ( mult > 9 )
total = total + ( mult - 9 );
else
total = total + mult;
}
}
decena = total / 10;
decena = Math.floor( decena );
decena = ( decena + 1 ) * 10;
final = ( decena - total );
if ( ( final == 10 && digito == 0 ) || ( final == digito ) ) {
alert( "La c\xe9dula ES v\xe1lida!!!" );
return true;
}
else
{
alert( "La c\xe9dula NO es v\xe1lida!!!" );
return false;
}
}
else
{
alert("La c\xe9dula no puede tener menos de 10 d\xedgitos");
return false;
}
}
Let's say your model name is User and the field in the database is card, you would do the following;
<?php
class User extends AppModel {
/**
* Validation rules
*/
public $validate = array(
'card' => array(
'validateCard' => array(
'rule' => array('validateCard'),
'message' => 'Card does not validate'
)
)
);
/**
* Custom validation rule
* #return bool
*/
public function validateCard($field) {
$cardNumber = $field['card'];
// Here, perform your logic and return a boolean
}
}
Also, make sure in your view, you're using the FormHelper to output the form inputs and everything should play nice. For example;
<?php
echo $this->Form->create();
echo $this->Form->input('User.card');
echo $this->Form->end();
Related
I’ve got a really large file, circa 10m rows, in which I’m trying to populate a column based on conditions on another column via a jsee macro. While it is quite quick for small files, it does take some time for the large file.
//pseudocode
//No sorting on Col1, which can have empty cells too
For all lines in file
IF (cell in Col2 IS empty) AND (cell in Col1 IS NOT empty) AND (cell in Col1 = previous cell in Col1)
THEN cell in Col2 = previous cell in Col2
//jsee code
document.CellMode = true; // Must be cell selection mode
totalLines = document.GetLines();
for( i = 1; i < totalLines; i++ ) {
nref = document.GetCell( i, 1, eeCellIncludeNone );
gsize = document.GetCell( i, 2, eeCellIncludeNone );
if (gsize == "" && nref != "" && nref == document.GetCell( i-1, 1, eeCellIncludeNone ) ) {
document.SetCell( i, 2, document.GetCell( i-1, 2, eeCellIncludeNone ) , eeAutoQuote);
}
}
Input File:
Reference
Group Size
14/12/01819
1
14/12/01820
1
15/01/00191
4
15/01/00191
15/01/00191
15/01/00198
15/01/00292
3
15/01/00292
15/01/00292
15/01/00401
5
15/01/00401
15/01/00402
1
15/01/00403
2
15/01/00403
15/01/00403
15/01/00403
15/01/00404
20/01/01400
1
Output File:
Reference
Group Size
14/12/01819
1
14/12/01820
1
15/01/00191
4
15/01/00191
4
15/01/00191
4
15/01/00198
15/01/00292
3
15/01/00292
3
15/01/00292
3
15/01/00401
5
15/01/00401
5
15/01/00402
1
15/01/00403
2
15/01/00403
2
15/01/00403
2
15/01/00403
2
15/01/00404
20/01/01400
1
Any ideas on how to optimise this and make it run even faster?
I wrote a JavaScript for EmEditor macro for you. You might need to set the correct numbers in the first 2 lines for iColReference and iColGroupSize.
iColReference = 1; // the column index of "Reference"
iColGroupSize = 2; // the column index of "Group Size"
document.CellMode = true; // Must be cell selection mode
sDelimiter = document.Csv.Delimiter; // retrieve the delimiter
nOldHeadingLines = document.HeadingLines; // retrieve old headings
document.HeadingLines = 0; // set No Headings
yBottom = document.GetLines(); // retrieve the number of lines
if( document.GetLine( yBottom ).length == 0 ) { // -1 if the last line is empty
--yBottom;
}
str = document.GetColumn( iColReference, sDelimiter, eeCellIncludeQuotes, 1, yBottom ); // get whole 1st column from top to bottom, separated by TAB
sCol1 = str.split( sDelimiter );
str = document.GetColumn( iColGroupSize, sDelimiter, eeCellIncludeQuotes, 1, yBottom ); // get whole 2nd column from top to bottom, separated by TAB
sCol2 = str.split( sDelimiter );
s1 = "";
s2 = "";
for( i = 0; i < yBottom; ++i ) { // loop through all lines
if( sCol2[i].length != 0 ) {
s1 = sCol1[i];
s2 = sCol2[i];
}
else {
if( s1.length != 0 && sCol1[i] == s1 ) { // same value as previous line, copy s2
if( s2.length != 0 ) {
sCol2[i] = s2;
}
}
else { // different value, empty s1 and s2
s1 = "";
s2 = "";
}
}
}
str = sCol2.join( sDelimiter );
document.SetColumn( iColGroupSize, str, sDelimiter, eeDontQuote ); // set whole 2nd column from top to bottom with the new values
document.HeadingLines = nOldHeadingLines; // restore the original number of headings
To run this, save this code as, for instance, Macro.jsee, and then select this file from Select... in the Macros menu. Finally, select Run Macro.jsee in the Macros menu.
I'm trying to develop an Expert Advisor, so far I can understand and write this which will place orders when a new bar opens.
int BarsCount = 0;
int start()
{ if ( Bars > BarsCount )
{ OrderSend( Symbol(), OP_BUY, 0.01, Ask, 2, NULL, NULL );
BarsCount = Bars;
}
return( 0 );
}
how to get the highest value of standard deviation for last 2 hours to a variable?
E.g.: lets say the EA runs in a 30 mins chart and the bar1 has the standard deviation value 0.003, and bar2 has 0.001, bar3 has 0.004 and bar4 has 0.001.
So, the highest value for past 4 hours is bar3 which has the value of 0.004, so how to get that value to a variable?
I'm trying to make the EA place orders when this formula is true:
( ( current_value_of_standard_deviation
/ highest_value_of_standard_deviation_for_last_2_hours
)
* 100
) > 10
Use built-in tools:
input int MA_period = 27;
int BarsCount = 0;
int nCells2CMP= ( PERIOD_H1 * 2 / PERIOD_CURRENT ) - 1;
double Sig2H[100];
void OnInit(){
...
}
void OnTick(){
if ( Bars > BarsCount ){
if ( BarsCount == 0 ){
for ( int i = MA_period; i > 0; i-- ){
Sig2H[i] = iStdDev( _Symbol,
PERIOD_CURRENT,
0,
MODE_SMA,
PRICE_CLOSE,
i
);
}
}
for ( int i = MA_period; i > 1; i-- ) Sig2H[i] = Sig2H[i-1];
Sig2H[1] = iStdDev( _Symbol, // symbol
PERIOD_CURRENT, // timeframe
MA_period, // MA averaging period
0, // MA shift
MODE_SMA, // MA averaging method
PRICE_CLOSE, // applied price
1 // shift
);
}
Sig2H[0] = iStdDev( _Symbol, // symbol
PERIOD_CURRENT, // timeframe
MA_period, // MA averaging period
0, // MA shift
MODE_SMA, // MA averaging method
PRICE_CLOSE, // applied price
0 // shift
);
if ( 0.1 < ( Sig2H[0]
/ Sig2H[ArrayMaximum( Sig2H,
nCells2CMP,
1
)
]
)
){...}
}
on getIndexes (int number , int size , int characters )
I have to add the converted number at end of array as I have to apply padding of 0 suppose its 231...
which means I have to put 6 zeros at start and then 20.
//Input characters and Lenght of Motif
char [] inputChars = {'a','c','g','t'} ;
int lengthOfMotif = 8 ;
public void map(Object key, Text value, Context context) throws IOException, InterruptedException
{
/*
* To generate all the combinations of lengthOfMotif i used formula or probability to count of all possible strings that will be power of ( inputChars length , elements in motif )
*
* Then i called my getIndexes method to get int[] of length lengthOfMotif representing an index from inputChars
*
* I generated a motif and made it key of Mapper and called minDistance returning minDistance,bestMatchingString,indexOfBestMatchingString and made it value for key motif
*
*
*/
for (int i = 0 ; i < Math.pow(inputChars.length, lengthOfMotif) ; i ++ )
{
String motif = "" ; // initialize the empty motif string
for ( int j : getIndexes ( i , lengthOfMotif , inputChars.length ) ) //loop on array returned by getIndexes() with indexes to select from inputChar Array to build the string
{
motif = motif+inputChars[j] ;
}
context.write(new Text(motif), new Text ( minDistance(motif,value.toString() ) ) ) ;
}
}
// It takes a number , length of resultant indexes , number of unique characters
/*
* I convert the number to base of unique characters so the max index that can be generated will be less than the power
* then place the number at end of indexes array which will keep the starting indexes to be 0
*
* As our length is 8 and characters are 4 so
* if my number is 0
* i converted it to base 4 so it will remain 0
* i placed it at end of indexes array so my array will be like
* 0 0 0 0 0 0 0 0
* which in our case if considered as index of inputChars it will return
* a a a a a a a a
* The max number will be 8 ^ 4 = 65536 as we are starting from 0 our max number will be 65536
* in base 4 65536 is 3 3 3 3 3 3 3 3 which if we consider indexes will become
* t t t t t t t t
* So every number from 0 to 65536 will be covered and each combination will be passed as key of mapper
*
*/
int[] getIndexes (int number , int size , int characters )
{
//init new result array
int[] result = new int[size] ;
// I stuck here
}
return result ;
}
//return concatinated string in format minDistance,bestMatching,index
/ in string
// 2 -> index -> 0
// 3 -> index -> 1
// 1 -> index -> 2
//Array has indexes 0 to 7
// so to add paadd
// 2 have to be at 5th index
// 3 have to be at 6th index
// 1 have to be at 7th index
// size variable has total required length that is 8
// so i subtracted length of 231 from 8. 8-3 = 5 + i = 5+0
// now i have to place second at 6th... so 8-3 = 5 + i = 5 + 1
// for 7th index 8 - 3 = 5 + i = 5 + 7
// i concatinated "" to make the character into string and Integer.parse int converted them to integer
// so 5 6 7 indexes will be filled with 2 3 1
result [ size-indexes.length()+i ] = Integer.parseInt( indexes.charAt(i) + "") ;
String [] tokens = values.iterator().next().toString().split(",");
int minDistance = Integer.parseInt ( tokens [ 0 ] ) ;
String bestMatching = tokens[ 1 ] ;
int index = Integer.parseInt( tokens [ 2 ] ) ;
int minimumDistance = minDistance ;
for ( Text t : values )
{
tokens = t.toString().split(",");
int distance = Integer.parseInt( tokens [ 0 ] ) ;
if ( distance < minDistance )
{
minDistance = distance ;
bestMatching = tokens [ 1 ] ;
index = Integer.parseInt( tokens [ 2 ] ) ;
}
minimumDistance = minimumDistance + distance ;
I would like to print a database-table to STDOUT. If the table-width is greater than the screen-width I would like to cut the column each with the same percentage (unless a table-width has reached min_width) until the table fits in the screen. I've tried to solve this with the posted subroutine. Does somebody know a shorter and more elegant algorithm to solve this problem?
sub cal_size {
my ( $maxcols, $ref ) = #_;
# $maxcols => screen width
# $ref => ref to an AoA; holds the table
my ( $max ) = cal_tab( $ref );
# $max => ref to an array; holds the length of the longest string of each column
# $tab = 2;
if ( $max and #$max ) {
my $sum = sum( #$max ) + $tab * #$max;
$sum -= $tab;
my #max_tmp = #$max;
my $percent = 0;
while ( $sum > $maxcols ) {
$percent += 0.5;
if ( $percent > 99 ) {
return;
}
my $count = 0;
for my $i ( 0 .. $#max_tmp ) {
# $min_width => columns width should not be less than $min_width if possible
next if $min_width >= $max_tmp[$i];
# no need to cut if the column width id less than min_width
next if $min_width >= minus_x_percent( $max_tmp[$i], $percent );
# don't cut if column width become less than min_width
$max_tmp[$i] = minus_x_percent( $max_tmp[$i], $percent );
$count++;
last if $sum <= $maxcols;
}
$min_width-- if $count == 0 and $min_width > 1;
# if no cuts but $sum > $maxcols reduce $min_width
$sum = sum( #max_tmp ) + $tab * #max_tmp;
$sum -= $tab;
}
my $rest = $maxcols - $sum;
while ( $rest > 0 ) { # distribute the rest
my $count = 0;
for my $i ( 0 .. $#max_tmp ) {
if ( $max_tmp[$i] < $max->[$i] ) {
$max_tmp[$i]++;
$rest--;
$count++;
last if $rest < 1;
}
}
last if $count == 0;
last if $rest < 1;
}
$max = [ #max_tmp ] if #max_tmp;
}
return $max;
}
sub minus_x_percent {
my ( $value, $percent ) = #_;
return int $value - ( $value * 1/100 * $percent );
}
This problem would be simple if it wasn't for the lower limit for the field widths. Once a field cannot get any smaller only the larger ones are eligible for scaling, so the calculation varies depending on whether all, none, or some of the fields have been scaled down to their limit.
The scaling has several bands, one per unique field width. As the fields are scaled down in equal proportion the smallest of them will be the first to hit the minimum field size limit. After that only the columns bigger than the smallest size can be reduced any further until the second smallest also reaches the limit.
This continues until all columns have reached their minimum size, after which the available space is just divided equally between the columns.
This program implements the calculations for that algorithm, and I think does what you want.
Note that the returned field widths are floating-point values and you must round them as you see fit.
use strict;
use warnings;
use List::Util 'max';
my $min_col_width = 10;
my $tab = 2;
my $widths = recalc_widths(80, [ 10, 15, 20, 25, 30 ]);
print join ' ', map sprintf('%.3f', $_), #$widths;
print "\n";
sub recalc_widths {
my ($target, $widths) = #_;
$target -= (#$widths - 1) * $tab;
my #sorted_widths = sort { $a <=> $b } #$widths;
my $num_limited = 0;
my $adjustable_total_width = 0;
$adjustable_total_width += $_ for #sorted_widths;
while (#sorted_widths) {
my $boundary = $sorted_widths[0];
my $scale = ($target - $num_limited * $min_col_width) / $adjustable_total_width;
if ($boundary * $scale >= $min_col_width) {
return [ map max($_ * $scale, $min_col_width), #$widths ];
}
while (#sorted_widths and $sorted_widths[0] == $boundary) {
shift #sorted_widths;
$adjustable_total_width -= $boundary;
$num_limited++;
}
}
return [ ($target / $num_limited) x $num_limited ];
}
output
10.000 10.333 13.778 17.222 20.667
I think it's better to use a proper module from CPAN. If you can calc the width of each column, then configure each row print with Text::Format
I need to calculate 5-star ratings like the one on Amazon website. I have done enough search to find what is the best algorithm, but I am not able to get a proper answer. For example, if these are the ratings
5 star - 252
4 star - 124
3 star - 40
2 star - 29
1 star - 33
totally 478 reviews
Amazon has calculated this to be "4.1 out of 5 stars". Can anyone tell me how this figure is arrived at? I am not able to get this just by doing average.
That's a weighted average, where you weigh each rating with the number of votes it got:
(5*252 + 4*124 + 3*40 + 2*29 + 1*33) / (252+124+40+29+33) = 4.11 and change
If you are start calculation of overall rating from beginning then this formula will help you.
Formula
((Overall Rating * Total Rating) + new Rating) / (Total Rating + 1)
Example
suppose you have no ratings till now then formula is like,
overall rating is "0" till now.
total rating "0"
and given rating is "4"
((0*0)+4)/1 = 4
If overall rating is "4.11" Total rating is "478" And new rating
giving by one user is "2"
then formula is like
((4.11 * 478)+ 2)/479 // 479 is increment of new rating from 478
a better way to do this,
rating = (sum_of_rating * 5)/sum_of_max_rating_of_user_count
example:
total users rated: 6
sum_of_max_rating_of_user_count: 6 x 5 = 30
sum_of_rating: 25
rating = (25 * 5) / 30
Done!
Yes, you can average them out:
(5 * 252 + 4 * 124 + 3 * 40 + 2 * 29 + 1 * 33) / 478 = 4.11
Super helpful reply by Blindy, here's the PHP code that's based on it. Some may find useful. The results will be 4.11 as per OP's example:
$ratings = array(
5 => 252,
4 => 124,
3 => 40,
2 => 29,
1 => 33
);
function calcAverageRating($ratings) {
$totalWeight = 0;
$totalReviews = 0;
foreach ($ratings as $weight => $numberofReviews) {
$WeightMultipliedByNumber = $weight * $numberofReviews;
$totalWeight += $WeightMultipliedByNumber;
$totalReviews += $numberofReviews;
}
//divide the total weight by total number of reviews
$averageRating = $totalWeight / $totalReviews;
return $averageRating;
}
How to build the above $ratings array
Example pseudo code, but which should work that explains how to build the $ratings array when info is stored in DB assuming you have a table called "ratings" and a column called "rating". In this case it's 1 join, you would need to do 4 joins to get all ratings, but this should get you started:
SELECT count(c1.rating) as one_star, count(c2.rating) as two_star
FROM ratings c1
LEFT OUTER JOIN
ratings c2
ON
c1.id = c2.id
WHERE
c1.rating = 1
AND
c2.rating = 2
another approach suggested in comments
SELECT SUM(rating = 1) AS one_s ,SUM(rating = 2) AS two_s ,SUM(rating = 3) as three_s FROM reviews where product_id = 9
This rating system is based on a weighted average or weighted mean. That is, they used the weight in terms of stars to compute a decimal value which rounds to 4.1. For example:
Sum of (weight * number of reviews at that weight) / total number of reviews
(5*252 + 4*124 + 3*40 + 2*29 + 1*33) / 478 = 4.1
Weighted average, sum the number of stars times its weight, and then divide it through by the total number of reviews.
According to your question your solution will be like this.
Sum of (Rate*TotalRatingOfThatRate)/ TotalNumberOfReviews
((5*252)+(4*124)+(3*40)+(2*29)+(1*33)) / (252+124+40+29+33)
output will be 4.1
in Javascript
function calcAverageRating(ratings) {
let totalWeight = 0;
let totalReviews = 0;
ratings.forEach((rating) => {
const weightMultipliedByNumber = rating.weight * rating.count;
totalWeight += weightMultipliedByNumber;
totalReviews += rating.count;
});
const averageRating = totalWeight / totalReviews;
return averageRating.toFixed(2);
}
const ratings = [
{
weight: 5,
count: 252
},
{
weight: 4,
count: 124
},
{
weight: 3,
count: 40
},
{
weight: 2,
count: 29
},
{
weight: 1,
count: 33
}
];
console.log(calcAverageRating(ratings));
In addition, I am just trying to make practical and full code for all.
My Json Object Array
var yourRatingData =[{
review_id:1,
customer_id:5,
customer_name:"Faysal",
rating:5,
review_content:"I like this product it's cool and best in quality"
},
{
review_id:2,
customer_id:6,
customer_name:"Adams",
rating:4,
review_content:"It's quality product though price a bit high"
},
{
review_id:3,
customer_id:8,
customer_name:"Jane",
rating:3,
review_content:"I like but should improve quality"
},
{
review_id:4,
customer_id:9,
customer_name:"Julia",
rating:1,
review_content:"It's not good"
}];
Rating Calculation
let _5star = yourRatingData.filter(r=>r.rating==5).length;
let _4star = yourRatingData.filter(r=>r.rating==4).length;
let _3star = yourRatingData.filter(r=>r.rating==3).length;
let _2star = yourRatingData.filter(r=>r.rating==2).length;
let _1star = yourRatingData.filter(r=>r.rating==1).length;
//Sum of individual star.
let sumOfRating = parseInt( _5star + _4star + _3star + _2star + _1star );
//Total number of rating
let overallRating = parseInt( 5*_5star + 4*_4star + 3*_3star + 2*_2star +1*_1star );
//Average of all rating
let averageRating = parseFloat(overallRating/sumOfRating);
//Percentage of each star rating
let _5starPercentage = parseInt((_5star/totalRating)*100);
let _4starPercentage = parseInt((_4star/totalRating)*100);
let _3starPercentage = parseInt((_3star/totalRating)*100);
let _2starPercentage = parseInt((_2star/totalRating)*100);
let _1starPercentage = parseInt((_1star/totalRating)*100);
I think it's helpful.
This is an example method using flutter,
double starRating = 5.0;
getRating() {
// ! Check Already Accepted by others or Not -----------------------------------
//
int totalof5s = 0;
int totalof4s = 0;
int totalof3s = 0;
int totalof2s = 0;
int totalof1s = 0;
//
FirebaseFirestore.instance
.collection('usersRating')
.where("passengerUid", isEqualTo: "GNblJJJsjicaA2vkXJNJ6XCAiwa2")
.snapshots()
.forEach((querySnapshot) {
if (querySnapshot.size > 0) {
querySnapshot.docs.forEach((element) async {
if (element["rating"] == 5) {
totalof5s++;
} else if (element["rating"] == 4) {
totalof4s++;
} else if (element["rating"] == 3) {
totalof3s++;
} else if (element["rating"] == 2) {
totalof2s++;
} else if (element["rating"] == 1) {
totalof1s++;
}
//
if (this.mounted) {
setState(() {
starRating = (5 * totalof5s +
4 * totalof4s +
3 * totalof3s +
2 * totalof2s +
1 * totalof1s) /
(totalof5s + totalof4s + totalof3s + totalof2s + totalof1s);
});
}
});
} else {
// This is default one in any case these user doesn't have any rating document exists
if (this.mounted) {
setState(() {
starRating = 5.0;
});
}
}
});
}
(Total nunber of star / total number of persons who review * 5 ) * 5
= Answer
Fixed decimals in js to 1.
answer.toFixed(1);
Example the total reviews of 5 person is 20 star.
(20/5*5)*5 = 4.0
I used this way to calculate ratings and it is working perfectly
let one_star = 0;
let two_star = 0;
let three_star = 0;
let four_star = 0;
let five_star = 0;
Object.values(reviews).forEach(({ rating }) => {
switch (rating) {
case 1: one_star++; break;
case 2: two_star++; break;
case 3: three_star++; break;
case 4: four_star++; break;
case 5: five_star++; break;
}
});
let sum = one_star + two_star + three_star + four_star + five_star;
let average = ((5 * five_star) + (4 * four_star) + (3 * three_star) + (2 * two_star) + (1 * one_star)) / (sum);
console.log(average);