How to grade scores in php - php

I'm trying to grade some scores according to highest average obtained..
Here's my scripts
$scores_AND_ID = 'M2377O=100,M2727B=100,M5821K=100,M7492F=97.75,M7973O=96,M3487I=94,M7969O=93.13,M1452V=92.5,M4653O=92.38,M4158J=92.25,M2881A=89.38,M6112S=28.63,';
$out_score = chop($scores_AND_ID, ',');
$rr2 = explode(",", $out_score);
$array_un = array_unique($rr2);
foreach ($array_un as $key => $value) {
if ($value == "") {
continue;
}
$postion = positionNumbers($key);//1st,2nd,3rd function
$sec = explode("=", $value);
rsort($sec);
$stdntID = $sec[0]; //Student number
$stdntAV = $sec[1]; //Student Average
mysql_query("UPDATE score_table SET grade='$postion' WHERE avg='$stdntAV' ");
}
I'm using foreach key to assign grade position but isn't working properly.
Here's my result
Here's what I need to achieve.
1. 100---1st
2. 100---1st
3. 100---1st
4. 98---4th
5. 89.5--5th
6. 89---6th
7. 89---6th
8. 80---8th
Thanks Guys

I think the code you want is this:
<?php
$scores_AND_ID = 'M7492F=97.75,M7973O=96,M3487I=94,M2377O=100,M2727B=100,M5821K=100,M7969O=93.13,M1452V=92.5,M4653O=92.38,M4158J=92.25,M2881A=89.38,M6112S=28.63,';
// Gets all of the entries from the source string
$scores_array = array_unique(array_filter(explode(',', $scores_AND_ID)));
// Sets up an associative array of values (student id => score)
$score_map = [];
foreach ($scores_array as $record) {
[ $student_id, $score ] = explode('=', $record);
$score_map[$student_id] = $score;
}
// Ensure values are sorted numerically descending
uasort($score_map, function ($a, $b) {
if ($a > $b) {
return -1;
}
if ($a == $b) {
return 0;
}
return 1;
});
// Gets the maximum value from the scores
$previous_score = max(array_values($score_map));
$rank = 1;
$incrementer = 0;
foreach ($score_map as $student => $score) {
// If the score hasn't changed from it's previous value
// we increment a counter instead of the rank
if ($score == $previous_score) {
$incrementer++;
// Once it's changed, we update the rank based on the incrementer
// and then reset the incrementer
} else {
$rank += $incrementer;
$incrementer = 1;
}
$previous_score = $score;
// Updating database is left as an exercise to the reader
}

You should not update your records if grade is already set. If you print your query instead of executing it you will see that you set grade 1st, then you overwrite it with 2nd and then with 3rd.

Related

How to use regular expression in the WHERE clause of query in Laravel?

I have a table named "Shows". There is a column "show_date". I want to retrieve the shows whose show_date is todays date.
Following is my query
$s = DB::table('shows')->get();
$a = DB::table('shows')->select('show_date')->get();
foreach ($s as $key => $value)
{
$date_test = date('Y-m-d');
$s_test = DB::table('shows')->where('show_date',preg_grep('/"'.$value->show_date.'"./', $a->show_date))->get();
echo "<pre>"; var_dump($s_test);
if(explode(" ",$value->show_date)[0] == date('Y-m-d'))
{
$shows1 = DB::table('shows')->where('id',$value->id)->get();
$s1 = DB::table('transactions')
->select(DB::raw("GROUP_CONCAT(selected_seats SEPARATOR '') as selected_seats"),'userid','amount','show_id')
->where("show_id","=",$value->id)
->groupBy('userid')
->groupBy('amount')
->orderBy('userid','ASC')
->orderBy('amount', 'DESC')
->get();
if($s1 != null)
{
echo $value->id;
$c = count($s1);
$sub_count1 = 0; $next_id = ""; $total_array = 0;
for($i=0;$i<$c;$i++)
{
$first_character = $s1[$i]->selected_seats;
$sub_count = substr_count($s1[$i]->selected_seats, ',');
$sub_count1 = $sub_count1 + $sub_count;//to get the total no. of seats
for($j=0,$k=0;$j<$sub_count;$j++,$k++)
{
// split the string with comma.
$s = explode(',',$first_character);
// get total no. of seat names listed in one row in table.eg A 1,B 2. Then $sub_count would be 2
$p = $s[$j][0];
}
}
// get seats for each show from transaction table.
$demo = DB::table('theater_setting')->select('row_seats_selling_price','row')->where('show_id',$value->id)->get();
foreach ($demo as $key => $val) {
$categoryArr[$val->row]=$val->row_seats_selling_price;
}
$demo4 = DB::table('theater_setting')->select('row_seats_selling_price','row')->where('show_id',$value->id)->get();
$demo3 = DB::table('transactions')->where('show_id',$value->id)->select('selected_seats','userid')->get();
for($p=0;$p<count($demo3);$p++)
{
$arr = explode(',', substr($demo3[$p]->selected_seats,0,-1));
$trans[] = $demo3[$p]->userid;
foreach ($arr as $k => $v)
{
$seats[$demo3[$p]->userid][]=$v;
}
}
foreach ($seats as $user_id=>$v)
{
for ($h=0; $h < count($v); $h++)
{
$e = explode(" ", $v[$h]);
$p = $e[0];
$demo_array[$p][$user_id][] = $v[$h];
}
$users = DB::table('users')->where('id',$user_id)->get();
}
return view('Backend.NewReportByShowsCategory2')->with([
's1'=>$s1,'shows1'=>$shows1,'demo'=>$demo,'categoryArr'=>$categoryArr,'demo3'=>$demo3,'demo4'=>$demo4,'demo_array'=>$demo_array]);
}
else
{
return view('Backend.NewReportByShowsCategory2')->with([
's1'=>$s1]);
}
}
}
I am getting the following error:
Object of class stdClass could not be converted to string
There is alternative way:
DB::table('shows')->where('show_date', 'REGEXP', Carbon\Carbon::now()->toDateString())->get();
You could convert show_date to a DATE and compare it with the current date -
$s_test = DB::table('shows')->whereRaw('DATE(show_date)=CURRENT_DATE')->get()
However, here's the regex query for selecting rows with a particular date (the current date in this case),
DB::table('shows')->whereRaw("show_date REGEXP '". Carbon\Carbon::now()->toDateString() . "'")->get()

Check if Variable is smaller than others, and which one its smaller than. PHP

I have been working on my scoring system and came accros this.
I have 4 vars.
$newscore
$score1
$score2
$score3
I want to see if new score is lower than the 3 others, and if so which ones. The scoring system requires you to have the lowest possible score.
I have the following code:
if($newscore > $score1){
if($newscore > $score2){
if($newscore < $score3){
//has to be score3 to replace.
}
}else{
...
}
}
But what I'm wondering is if I will have to continue on with all these if statements, or is there something a lot shorter and easier? I need to replace the the score that it is smaller than, but not the one its larger than. Score 1 2 and 3 are all the players stats. And if I do have to continue on with all the if statements, how would the code look (its baffling my logic)?
you should probably use an array
$scores = array(8, 15, 10); //previous scores
$new_score = 5;
$new_score_smallest = true;
foreach($scores as $score) {
if($score < $new_score) {
$new_score_smallest = false;
}
}
if($new_score_smallest) {
echo "Best score!";
}
else {
echo "Not the best score :(";
}
If you only want to remember the 3 best scores:
$scores = array(5, 6, 8);
$new_score = 7;
for($i = 0; $i < count($scores); $i++) {
if($new_score < $scores[$i]) {
$scores[$i] = $new_score;
break;
}
}
You could do something like the following:
EDIT: As you're using a database, you would execute the query similar to this:
SELECT scores FROM scores_table replacing the table name and column name with your corresponding data.
$scores = [$score1, $score2] // add as many as you like
$new_score = $scores[0]; // assign a baseline
foreach ($scores as $score) {
if ($score < $new_score) {
$new_score = $score;
}
}
Hope that helps.
You can use array_search and min
$newscore = 2;
$scores = array($score1, $score2, $score3);
if($newscore < min($scores)){
$scores[array_search(min($scores), $scores)] = $newscore;
}
array $score lowest score will be updated if $newscore is inferior
Put your scores in an array or anything iterable (like a query result, whether you use PDO or mysqli).
Let's say your scores are in $scores array (it will be the same if $score is a PDOStatement for example) and ordered (use ORDER ASC in your query):
$scores = [105, 201, 305];
$newscore = '186';
$hiscore = false;
$beaten = [];
foreach ($score as $k => $score) {
if ($newscore > $score) {
$hiscore = true;
$beaten[] = $score;
unset($scores[$k]);
}
}
if ($hiscore) {
echo 'New high score!'.PHP_EOL;
echo 'Better than '.implode(', ', $beaten).PHP_EOL;
echo 'But not better than '.implode(', ', $scores);
} else {
echo 'Try harder!';
}
<?php
$newscore = 78;
$score1 = 23;
$score2 = 201;
$score3 = 107;
$max = max([$score1, $score2, $score3]);
if ($max < $newscore) {
echo "New best score ! ({$newscore})";
} else {
echo "Not the best score !\nCurrent: {$newscore}\nBest: {$max}";
}

Determine and do stuff in foreach loop except the last iteration

I am looping a foreach and i need to make some logic like this:
if the iteration is not the last. Gather up the prices. when the iteration is the last. subtract from the total with the gathered up prices. except the last iteration price. I got the following code not. but it's not working.
$i = 0;
$credit = '';
$count = count($reslist);
foreach ($reslist as $single_reservation) {
//All of the transactions to be settled by course
//$credit = $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
if ($i > $count && $single_reservation != end($reslist)) {
$gather_sum_in_czk += $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
$credit = $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
}
//Last iteration need to subtract gathered up sum with total.
else {
$credit = $suminczk - $gather_sum_in_czk;
}
$i++;
}
EDIT: TRYING TO GATHER UP PRICES FOR ALL INTERACTIONS EXECPT LAST:
if ($i != $count - 1 || $i !== $count - 1) {
$gather_sum_in_czk += $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
$credit = $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
}
else {
$credit = $suminczk - $gather_sum_in_czk;
}
The SPL CachingIterator is always one element behind its inner iterator. It can therefore report whether it will produce a next element via ->hasNext().
For the example I'm choosing a generator to demonstrate that this approach doesn't rely on any additional data like e.g. count($array).
<?php
// see http://docs.php.net/CachingIterator
//$cacheit = new CachingIterator( new ArrayIterator( range(1,10) ) );
$cacheit = new CachingIterator( gen_data() );
$sum = 0;
foreach($cacheit as $v) {
if($cacheit->hasNext()) {
$sum+= $v;
}
else {
// ...and another operation for the last iteration
$sum-=$v;
}
}
echo $sum; // 1+2+3+4+5+6+7+8+9-10 = 35
// see http://docs.php.net/generators
function gen_data() {
foreach( range(1,10) as $v ) {
yield $v;
}
}
foreach-ing an array in PHP returns both the key (integer index if pure array) and value. To be able to use the value, use the following construct:
foreach ($array as $key => $value) {
...
}
then you can check whether $key >= count($array) - 1 (remember in a 0-based array, the last element is count($array) - 1.
Your original code almost works, just wrong in the if condition. Use $i >= $count - 1 instead of $i > $count.

Incrementing through a MYSQL result set without stopping

I am trying to increment through a result set from my table.
I attempt to display the next three results using an increment. This is working fine.
For example;
current = 5.
It then displays the next three: 6,7,8
It can also display the previous three: 4,3,2
The problem comes when I reach the last couple or minimum couple of results. It will currently stop;
current = 23
next: 24, 25
I cannot figure out to loop through to the last or first few results.
E.g. I want it to do this:
current = 2
display previous three: 1, 25, 24
AND FOR next:
current = 23:
display next three: 24, 25, 1
I'm returning these as arrays. Code:
$test_array = array();
$no = 1;
while($results=mysql_fetch_assoc($test_query))
{
$test_array[] = array('test_id' => $results['id'],
'path' => $results['Path'],
'type' => $results['FileType']
'no' => $no);
$no++;
}
$current_no = 0;
if(is_array($test_array) && count($test_array)>0)
{
foreach($test_array as $key=>$array)
{
if($array['test_id']==intval($db_res['current_id']))
{
$current[] = $array;
$current_no = intval($key+1);
}
else
//error
if(intval($current_no)>0)
{
//Next 3
for($i=0;$i<3;$i++)
{
if(isset($test_array[intval($current_no+$i)]) && is_array($test_array[intval($current_no+$i)]))
{
$next[] = $test_array[intval($current_no+$i)];
}
else
break;
}
//Previous 3
for($i=2;$i<5;$i++)
{
if(isset($test_array[intval($current_no-$i)]) && is_array($test_array[intval($current_no-$i)]))
{
$previous[] = $test_array[intval($current_no-$i)];
}
else
break;
}
break;
}
else
//error
}
}
else
//error
If anyone has any ideas on how to help, that would be great!
Find $key for $current and set $next_key = $prev_key = $key;
Find last key $max = count($test_array) - 1;
Increase $next_key & decrease $prev_key 3 times (and check if
boundary is reached):
Loop might look like this.
for ($i = 1; $i <= 3; $i++)
{
$next_key = ($next_key == $max) ? 0 : $next_key + 1;
$prev_key = ($prev_key == 0) ? $max : $prev_key - 1;
$next[] = $test_array[$next_key];
$prev[] = $test_array[$prev_key];
}

Closest number in array, but on Monopoly table

I have a monopoly game in progress and I need to retrieve the closest location from given value. I get available closest locations like this:
function Field_GetNearestByCategory($current,$category) {
$current = (int)$current;
$category = SQLEscape($category);
$s = "SELECT ID,Location FROM `card` WHERE Category='$category' AND Location <> $current";
$qr = SQLQuery($s);
$locs = array();
while($r = SQLGetArray($qr)) {
$locs[] = $r[1];
}
return $locs;
}
I have found solution for getting the closest value in array but problem occurs when $current == 40 and next closest field should be 6 (lets say we want to go to closest railroads).
function closest($search, $arr)
{
$closest = null;
foreach($arr as $item)
{
if($closest == null || abs($search - $closest) > abs($item - $search))
{
$closest = $item;
}
}
return $closest;
}
Please note that if $current == 40, anything below it is FAR away since Monopoly goes in one direction so 1 is closer to 40 than 39.
UPDATE:
I have found solution, thanks everyone
function closest($search, $arr) {
$c = null;
sort($arr);
foreach($arr as $k) {
if($k > $search) { return $k; }
else {
if(!$c) $c = $k;
}
}
return $c;
}
Here's a query that adds a "distance" field (the distance ahead the square is from $current) - mysql syntax for the CASE statement
SELECT ID, Location,
CASE WHEN Location < $current THEN Location + 40 - $current
ELSE Location - $current
END
AS Distance
FROM `card` WHERE Category='$category' AND Location <> $current

Categories