Php level and exp system - php

How can i make a level system where i have 2 table, one for the level and another for amount of exp earned?
I want to be able to manage the different exp requierments myself, like level 2 will need 340exp and level 3 need 450exp. I dont want to set one exp amount and then multiply it. I want to manage the whole system.
I also want to set default level and max level, and give exp directly to the database column without too much problem (for forum posts etc).
I have seen a few questions here but i find them outdated or just not what im looking for.
PS: sorry for bad english and bad explenation.

I found a realy good solution and was able to rewrite it to work with my setup. if anyone is interested i will leave the original link and my edit of it bellow.
my edit:
<?php
// Connect to your database like you normally do, then get any value into the $count variable
$count = $exp;
if($level == 0){
$lvl = 1;
}else{
$lvl = $level;
}
if ($count >= 12800) { $lvl = 10; }
else if ($count >= 6400) { $lvl = 9; }
else if ($count >= 3200) { $lvl = 8; }
else if ($count >= 1600) { $lvl = 7; }
else if ($count >= 800) { $lvl = 6; }
else if ($count >= 400) { $lvl = 5; }
else if ($count >= 200) { $lvl = 4; }
else if ($count >= 100) { $lvl = 3; }
else if ($count >= 50) { $lvl = 2; }
// Render stars or any graphics/images according to dynamic $lvl number
$stars = "";
$i = 1;
while ($i <= $lvl) {
$stars .= "★";
$i++;
}
echo "level $lvl";
?>
Original link:
https://www.developphp.com/video/PHP/Experience-Level-Evaluation-Programming-Tutorial

Related

Get lowest price on sum of combinations in given array

This code is working fine when the array length is 8 or 10 only. When we are checking this same code for more than 10 array length.it get loading not showing the results.
How do reduce my code. If you have algorithm please share. Please help me.
This program working flow:
$allowed_per_room_accommodation =[2,3,6,5,3,5,2,5,4];
$allowed_per_room_price =[10,30,60,40,30,50,20,60,80];
$search_accommodation = 10;
i am get subsets = [5,5],[5,3,2],[6,4],[6,2,2],[5,2,3],[3,2,5]
Show lowest price room and then equal of 10 accommodation; output like as [5,3,2];
<?php
$dp=array(array());
$GLOBALS['final']=[];
$GLOBALS['room_key']=[];
function display($v,$room_key)
{
$GLOBALS['final'][] = $v;
$GLOBALS['room_key'][] = $room_key;
}
function printSubsetsRec($arr, $i, $sum, $p,$dp,$room_key='')
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if ($i == 0 && $sum != 0 && $dp[0][$sum]) {
array_push($p,$arr[$i]);
array_push($room_key,$i);
display($p,$room_key);
return $p;
}
// If $sum becomes 0
if ($i == 0 && $sum == 0) {
display($p,$room_key);
return $p;
}
// If given sum can be achieved after ignoring
// current element.
if (isset($dp[$i-1][$sum])) {
// Create a new vector to store path
// if(!is_array(#$b))
// $b = array();
$b = $p;
printSubsetsRec($arr, $i-1, $sum, $b,$dp,$room_key);
}
// If given $sum can be achieved after considering
// current element.
if ($sum >= $arr[$i] && isset($dp[$i-1][$sum-$arr[$i]]))
{
if(!is_array($p))
$p = array();
if(!is_array($room_key))
$room_key = array();
array_push($p,$arr[$i]);
array_push($room_key,$i);
printSubsetsRec($arr, $i-1, $sum-$arr[$i], $p,$dp,$room_key);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
function printAllSubsets($arr, $n, $sum,$get=[])
{
if ($n == 0 || $sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
// $dp = new bool*[$n];
$dp = array();
for ($i=0; $i<$n; ++$i)
{
// $dp[$i][$sum + 1]=true;
$dp[$i][0] = true;
}
// Sum arr[0] can be achieved with single element
if ($arr[0] <= $sum)
$dp[0][$arr[0]] = true;
// Fill rest of the entries in dp[][]
for ($i = 1; $i < $n; ++$i) {
for ($j = 0; $j < $sum + 1; ++$j) {
// echo $i.'d'.$j.'.ds';
$dp[$i][$j] = ($arr[$i] <= $j) ? (isset($dp[$i-1][$j])?$dp[$i-1][$j]:false) | (isset($dp[$i-1][$j-$arr[$i]])?($dp[$i-1][$j-$arr[$i]]):false) : (isset($dp[$i - 1][$j])?($dp[$i - 1][$j]):false);
}
}
if (isset($dp[$n-1][$sum]) == false) {
return "There are no subsets with";
}
$p;
printSubsetsRec($arr, $n-1, $sum, $p='',$dp);
}
$blockSize = array('2','3','6','5','3','5','2','5','4');
$blockvalue = array('10','30','60','40','30','50','20','60','80');
$blockname = array("map","compass","water","sandwich","glucose","tin","banana","apple","cheese");
$processSize = 10;
$m = count($blockSize);
$n = count($processSize);
// sum of sets in array
printAllSubsets($blockSize, $m, $processSize);
$final_subset_room = '';
$final_set_room_keys = '';
$final_set_room =[];
if($GLOBALS['room_key']){
foreach ($GLOBALS['room_key'] as $set_rooms_key => $set_rooms) {
$tot = 0;
foreach ($set_rooms as $set_rooms) {
$tot += $blockvalue[$set_rooms];
}
$final_set_room[$set_rooms_key] = $tot;
}
asort($final_set_room);
$final_set_room_first_key = key($final_set_room);
$final_all_room['set_room_keys'] = $GLOBALS['room_key'][$final_set_room_first_key];
$final_all_room_price['set_room_price'] = $final_set_room[$final_set_room_first_key];
}
if(isset($final_all_room_price)){
asort($final_all_room_price);
$final_all_room_first_key = key($final_all_room_price);
foreach ($final_all_room['set_room_keys'] as $key_room) {
echo $blockname[$key_room].'---'. $blockvalue[$key_room];
echo '<br>';
}
}
else
echo 'No Results';
?>
I'm assuming your task is, given a list rooms, each with the amount of people it can accommodate and the price, to accommodate 10 people (or any other quantity).
This problem is similar to 0-1 knapsack problem which is solvable in polynomial time. In knapsack problem one aims to maximize the price, here we aim to minimize it. Another thing that is different from classic knapsack problem is that full room cost is charged even if the room is not completely occupied. It may reduce the effectiveness of the algorithm proposed at Wikipedia. Anyway, the implementation isn't going to be straightforward if you have never worked with dynamic programming before.
If you want to know more, CLRS book on algorithms discusses dynamic programming in Chapter 15, and knapsack problem in Chapter 16. In the latter chapter they also prove that 0-1 knapsack problem doesn't have trivial greedy solution.

Reverse long PHP if function for number calculation

I'm making application for recording and processing company leave records using PHP and mysql. In my application I have to process three main leave type as below with their respective counts.
causal - 7
annual - 14
medical - 7
In my database I have table called leaves and it contian those three columns and their values respectively as follows
---name----casual----annual----medical
---jhon------7---------14--------7---
---mary------7---------14--------7---
---bill------5----------3--------0---
when employee applying a leave PHP function check available leave counts and subtract applied leave number from those three values like this
if leave type is casual and leave count is 15 it should be subtract both casual, medical and annual leaves to fulfill the employees leave requirement.I managed to implement up to this part. below is my code
if ($ltype == "medical")
{
if ($medical >= $hmd)
{
$medical-= $hmd;
}
else
{
$tval = $hmd - $medical;
$tval2 = $hmd - $tval;
$medical-= $tval2;
if ($casual >= $tval && $tval > 0)
{
$casual-= $tval;
}
else
{
$tval3 = $tval - $casual;
$tval4 = $tval - $tval3;
$casual-= $tval4;
if ($annual >= $tval3 && $tval3 > 0)
{
$annual-= $tval3;
}
else
{
$tval5 = $tval3 - $annual;
$tval6 = $tval3 - $tval5;
$annual-= $tval6;
$nopay += $tval5;
}
}
}
}
I have three code sets for three leave types and above code do the math as what I want. But my problem is when sometime users want to re-add those subtracted leave to the leave table. when comes to this I have to calculate this function reverse for get the exact numbers subtracted by each column form the first function. then I planned to calculate add how many leaves subtracted by each columns to the end of the leave record. but when reversing this also not working since those records not process as any order.
I want to implement way to re-add those leaves to the leaves table without any error.
I know my method may not suitable for this type of problem and this is extremely basic programming question. could someone please explain me how do I revers my first function exactly as the same or is there any other programming concepts that should I follow for solve these type of problems.
Okay, well assuming $hmd is number of days...this should get you very close:
http://sandbox.onlinephpfunctions.com/code/f16d899de4318a89e1d80e8737c49b079a5ee179
<?php
$ltype = 'medical';
$casual = 7;
$annual = 15;
$medical = 7;
$nopay = 0;
$hmd = 9;
echo "medical $medical, casual $casual, annual $annual, nopay $nopay\n";
if ($ltype == "medical") {
if ($medical >= $hmd) {
$medical -= $hmd;
} else {
// sorry no more med leave
$rem = $hmd - $medical;
$medical = 0;
if ($casual >= $rem && $rem > 0) {
$casual -= $rem;
} else {
// sorry no more cas leave
$rem2 = $rem - $casual;
$casual = 0;
if ($annual >= $rem2 && $rem2 > 0) {
$annual -= $rem2;
} else {
// sorry now you owe us money
$nopay += ($rem2 - $annual);
$annual = 0;
}
}
}
}
echo "medical $medical, casual $casual, annual $annual, nopay $nopay\n";
// need to set these to know when to "roll" to the next leave type...
$max_casual = 7;
$max_annual = 15;
$max_medical = 7;
if ($ltype == "medical") {
$rem = 0; // remainder after paying back nopay
if ($nopay >= $hmd) {
$nopay -= $hmd;
// well, we put some back but you still owe us!
} else {
// alright you paid it back!
$rem = $hmd - $nopay;
$nopay = 0;
}
if ($rem > 0) {
// let's restore some annual
$annual += $rem;
if ($annual > $max_annual) {
$rem = $annual - $max_annual;
$annual = $max_annual;
} else {
$rem = 0;
}
}
if ($rem > 0) {
// let's restore some casual
$casual += $rem;
if ($casual > $max_casual) {
$rem = $casual - $max_casual;
$casual = $max_casual;
} else {
$rem = 0;
}
}
if ($rem > 0) {
// whoa you're rolling in days off
$medical += $rem;
if ($medical > $max_medical) {
$rem_not_possible = $medical - $max_medical;
$medical = $max_medical;
} else {
$rem = 0;
}
}
}
echo "medical $medical, casual $casual, annual $annual, nopay $nopay\n";

Sorting arrays with uncertain data

I am crafting a script for a browser game that will generate a random animal for the player to battle with anywhere from 0-5 markings. The markings on that animal are randomly generated and are fed into a custom imagick function, which will add them in order as they appear in the array.
While the markings are randomly decided, there are a lot of rules to how they are supposed to appear on an animal, for instance markings in the "full body" region show above markings in the "belly" region. To better explain, I'll attach an image of the tester so far:
So to break down the 5 markings on this randomly generated animal, the eyeshadow marking belongs to eye region, undertail belongs to tail, streaks belongs to fullbody, appaloosa belongs to back, and okapi belongs to legs. The order right now is just added as the script looped through the database and randomly selected markings, so okapi (the stripes on the legs) is on top since it was the last on in the array, and the last one added. But following the order rules, the last one in the array should have been streaks (the horizontal streaks across the body), since fullbody markings go on top.
Here is the code the selects markings, this is done using the Laravel engine:
// Determine number of markings
$num = mt_rand(1,10);
if ($num == 1) {
$markingNum = 0;
} elseif ($num > 1 && $num < 4) {
$markingNum = 1;
} elseif ($num > 4 && $num < 6) {
$markingNum = 2;
} elseif ($num > 6 && $num < 8) {
$markingNum = 3;
} elseif ($num > 8 && $num < 10) {
$markingNum = 4;
} else {
$markingNum = 5;
}
// Calculate Marking type and color
$markings = array();
if ($markingNum > 0) {
for ($m = 0 ; $m < $markingNum; $m++) {
// Set color values (pulls from the "pallet" selected earlier in the code, which will determine the range of color that marking can be)
if ($m == 1) {
$pal = $pallet->marking1;
} elseif ($m == 2) {
$pal = $pallet->marking2;
} elseif ($m == 3) {
$pal = $pallet->marking3;
} elseif ($m == 4) {
$pal = $pallet->marking4;
} else {
$pal = $pallet->marking5;
}
// Pull previous marking info
if (count($markings) != 0) {
$previous = DataMarking::whereIn('name', array_keys($markings))->get();
// This pulls the regions of the current markings in the array so it won't select a region that already has a marking.
foreach ($previous as $p) {
$regions[$p->region] = $p->name;
}
// Uncommon marking (10% chance)
$r = mt_rand(1, 10);
if ($r == 10) {
$marking = DataMarking::where('rarity', 1)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
// Common markings
} else {
$marking = DataMarking::where('rarity', 0)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
}
// Colors marking
if ($pal == 0) {
$markingColor = rand_color();
} else {
$range = ColorRange::where('id', $pal)->firstOrFail();
$markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1));
}
$markings[$marking->name] = $markingColor;
} else {
// Uncommon marking (10% chance)
$r = mt_rand(1, 10);
if ($r == 10) {
$marking = DataMarking::where('rarity', 1)
->where('public', 1)
->orderByRaw("RAND()")->first();
// Common marking
} else {
$marking = DataMarking::where('rarity', 0)
->where('public', 1)
->orderByRaw("RAND()")->first();
}
// Colors marking
if ($pal == 0) {
$markingColor = rand_color();
} else {
$range = ColorRange::where('id', $pal)->firstOrFail();
$markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1));
}
$markings[$marking->name] = $markingColor;
}
}
}
I figure I can accomplish this with a lot of complex if statements but it just doesn't seem like an elegant solution to me. In addition, there is an exception: 'Gradient', a fullbody marking, goes underneath everything even though it is a full body marking. So far it is the only marking with this sort of exception to it, though.
I have tried using various sort functions offered by PHP but I am not having much luck. uksort seems the most promising, but since the value we are sorting by exists in the database and not in the array we are sorting (the imagick function has to be fed a marking => color array format), it's proving difficult to work with.
Tl;dr: I need to reorder an array that an uncertain amount of data based off of values that exist in the DB for the keys (the region for the markings). What's the most elegant way to accomplish this?
Here are some optimizations to your code, there are comments inline to describe what was done. This is obviously not finished as there are some things Marcin pointed out in his answer that would be better.
// Determine number of markings
$num = mt_rand(1,10);
// Removed redundent $num > X as the conditions were already meet that it was > X by the previous if statement
if ($num == 1) {
$markingNum = 0;
} else if ($num < 4) {
$markingNum = 1;
} else if ($num < 6) {
$markingNum = 2;
} else if ($num < 8) {
$markingNum = 3;
} else if ($num < 10) {
$markingNum = 4;
} else {
$markingNum = 5;
}
// Calculate Marking type and color
$markings = array();
if ($markingNum > 0) {
for ($m = 1 ; $m <= $markingNum; $m++) { // incrimented to 1 and <= so we can dynamically select elements
// Set color values (pulls from the "pallet" selected earlier in the code, which will determine the range of color that marking can be)
$pal = $pallet->{'marking' . $m}; // Removed if/else and replaced with a dynamic variable
// Uncommon marking (10% chance)
$r = mt_rand(1, 10);
// removed duplicate database selections for a simple $rarity variable that accomplishes the same task
if ($r == 10) {
$rarity = 1;
} else {
$rarity = 0;
}
$marking = DataMarking::where('rarity', $rarity)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', $regions)
->orderByRaw("RAND()")
->first();
// Colors marking
if ($pal == 0) {
$markingColor = rand_color();
} else {
$range = ColorRange::where('id', $pal)->firstOrFail();
$markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1));
}
$markings[$marking->name] = $marking; // adds all of the marking data, this is where you could have a z-index in the database
$markings[$marking->name] = $markingColor; // add your color to your marking data
$regions[] = $marking->region;
}
}
I won't answer your question, but looking at your code there are a lot of space for improvements.
Consider this:
if ($m == 1) {
$pal = $pallet->marking1;
} elseif ($m == 2) {
$pal = $pallet->marking2;
} elseif ($m == 3) {
$pal = $pallet->marking3;
} elseif ($m == 4) {
$pal = $pallet->marking4;
} else {
$pal = $pallet->marking5;
}
It could be changed for something much simpler:
$pa1 = (in_array($m,range(1,4))) ? $pallet->marking{$m} : $pallet->marking5;
Same for:
if ($r == 10) {
$marking = DataMarking::where('rarity', 1)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
// Common markings
} else {
$marking = DataMarking::where('rarity', 0)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
}
if could be rewritten to:
$marking = DataMarking::where('rarity', ($r == 10) ? 1 : 0)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
Of course in above ORDER BY RAND() might be not the best solution because of performance reasons.
You should really care about amount of your code and duplication or you'll soon be lost in what you are doing

A Logical Algorithm In PHP

I'm a beginner learning PHP. I have tried to make a loop that has a different behaviour for both even and odd numbers. I've been playing around with it for a while, yet I still can't get it to work. Has anyone got a solution?
$count = 0;
$mod = $count % 2;
while ($count < 10)
{
if ($mod == 0) {
echo "even, ";
} else {
echo "odd, ";
}
$count++;
}
A silly mistake, mod inside while() loop.
$count = 0;
while ($count < 10) {
$mod = $count % 2; //Here
if ($mod == 0) {
echo "even, ";
} else {
echo "odd, ";
}
$count++;
}
$count = 0;
$mod = $count %2;
Is were your problem is.
You have to use the modulus (%) operator inside the for loop. Also, there is no need to store the value from the use of the modulus operator at all, it can be compared directly inside the for-loop.
for ($count = 0; $count < 10, $count++) {
if ($count % 2 == 0) {
echo "even, ";
} else {
echo "odd, ";
}
}
You can also switch the while to a for like this.
Welcome to PHP.
Edit #1:
As you are getting a new value of $count every execution of the for-loop the old value if $count % 2 will be incorrect. It has to recalculate for every $count. First it checks if 0 is divisible by 2, then onto 1 and so forth. For every value of $count you have to check the divisibility.
In most programming languages you aren't computing a variable onto another, instead you are taking the value of the variable. Like $a = $b + $c; in that case, if you change the value of $b or $c it does not automatically update $a. Instead you have to call $a = $b + $c again. It is the same with % operator.
$count = 0;
while ($count < 10) {
$mod = $count % 2;
if ($mod == 0) {
echo "even, ";
} else {
echo "odd, ";
}
$count++;
}
use for loop instead of while loop
for($count=0;$count<10;$count++)
{
if(($count % 2) == 0)
echo "even,";
else
echo "odd,";
}

PHP - Project Euler #2

I got the answer fine, but when I run the following code,
$total = 0;
$x = 0;
for ($i = 1;; $i++)
{
$x = fib($i);
if ($x >= 4000000)
break;
else if ($x % 2 == 0)
$total += $x;
print("fib($i) = ");
print($x);
print(", total = $total");
}
function fib($n)
{
if ($n == 0)
return 0;
else if ($n == 1)
return 1;
else
return fib($n-1) + fib($n-2);
}
I get the warning that I have exceeded the maximum execution time of 30 seconds. Could you give me some pointers on how to improve this algorithm, or pointers on the code itself? The problem is presented here, by the way.
Let's say $i equal to 13. Then $x = fib(13)
Now in the next iteration, $i is equal to 14, and $x = fib(14)
Now, in the next iteration, $i = 15, so we must calculate $x. And $x must be equal to fib(15). Now, wat would be the cheapest way to calculate $x?
(I'm trying not to give the answer away, since that would ruin the puzzle)
Try this, add caching in fib
<?
$total = 0;
$x = 0;
for ($i = 1;; $i++) {
$x = fib($i);
if ($x >= 4000000) break;
else if ($x % 2 == 0) $total += $x;
print("fib($i) = ");
print($x);
print(", total = $total\n");
}
function fib($n) {
static $cache = array();
if (isset($cache[$n])) return $cache[$n];
if ($n == 0) return 0;
else if ($n == 1) return 1;
else {
$ret = fib($n-1) + fib($n-2);
$cache[$n] = $ret;
return $ret;
}
}
Time:
real 0m0.049s
user 0m0.027s
sys 0m0.013s
You'd be better served storing the running total and printing it at the end of your algorithm.
You could also streamline your fib($n) function like this:
function fib($n)
{
if($n>1)
return fib($n-1) + fib($n-2);
else
return 0;
}
That would reduce the number of conditions you'd need to go through considerably.
** Edited now that I re-read the question **
If you really want to print as you go, use the output buffer. at the start use:
ob_start();
and after all execution, use
ob_flush();
flush();
also you can increase your timeout with
set_time_limit(300); //the value is seconds... so this is 5 minutes.

Categories