Difficult algorithm: badge balancing, math distribution - php

I have a quite interesting problem that's making my head twist. I'm working on a small system consisting of users and awards (called badges). There is a special badge that is awarded to users depending on the following criteria: 10 bronze badges, 5 silver badges and 1 gold badge. That is pretty simple, however, if an user has 8 bronze badges, 7 silver badges and 1 gold badge, he can use his 2 additional silver badges as bronze ones.
This happens everytime the user has available "higher" badges to distribute. Again, for example, if he has 8 bronze badges, 4 silver badges and 4 gold badges, he can "transform" 2 of his gold badges into bronze and 1 to silver, in order to earn the special badge.
I have absolutely no idea of how to do this. I've tried with various loops, ifs, but i can never distribute properly. Maybe someone can help me out?

The user needs at least 1 gold badge, at least 6 badges that are either silver or gold, and at least 16 badges that are bronze, silver or gold.
The pseudocode is
count(gold) >= 1
&& count(gold) + count(silver) >= 6
&& count(gold) + count(silver) + count(bronze) >= 16
If you also have a diamond medal that can swap for a gold, silver or bronze then include that as well, like
count(diamond) + count(gold) >= 1
&& count(diamond) + count(gold) + count(silver) >= 6
// etc
Or you could use a 'medal rank' so that you can do something simpler like
count(rank of gold or higher) >= 1
&& count(rank of silver or higher) >= 6
&& count(rank of bronze or higher) >= 16

$bank['g'] -= $price['g'];
$bank['s'] -= $price['s'];
$bank['b'] -= $price['b'];
if ($bank['b'] < 0) {
$bank['s'] += $bank['b'];
$bank['b'] = 0;
}
if ($bank['s'] < 0) {
$bank['g'] += $bank['s'];
$bank['s'] = 0;
}
if ($bank['g'] < 0) {
//not enough cash
} else {
//ok
}

One way would be to start with the "highest" badge, subtract the number that are required, and convert the rest to the next badge. So:
Take away one gold badge.
Convert all remaining gold badges to silver.
Take away five silver badges.
Convert all remaining silver badges to bronze.
Take away 10 bronze badges.
If any of the "take away" steps fails, then they don't qualify for the badge. This is simple and it's trivial to modify it for other badge quantities or exchange rates.

Related

Calculate rating for 5 stars depending of reviews

I have good reviews, and I have bad reviews. I need calculate rating from this reviews for post.
Example:
Post 1 have 1 good reviews, and 2 bad reviews
Post 2 have 12 good reviews, and 5 bad reviews
Post 3 have 0 good reviews, and 0 bad reviews
How I can calculate rating? I need for post get 5 stars. I need score up to 5 stars or less. May be I need this formula?
$score = ($good_reviews * $bad_reviews) / 5; //get rating stars
But I don't get 5, or less number. How I can do it correctly?
Maybe you want this:
$rating = $good_reviews
? intval ( 5.4 * $good_reviews / ( $good_reviews + $bad_reviews))
: 0;
And now step by step:
SUM := $good_reviews + $bad_reviews is the sum of all reviews.
RATE := $good_reviews / SUM is the general rating of $good_reviews to the sum of reviews. The result is in the range 0.000 to 1.000 .
Multiplying it with 5.4 expands the range to 0.000 to 5.400. Its a little bit tricky to allow some bad votes for a 5 stars ranking. The factor can be every number between 5.000 and 5.9999999.
intval() reduces the number to an int from 0 to 5 (your stars).
The alternative by ?: avoids an division by zero error.
That formula will not give you what you need. It will only multiply good with bad and divide by 5. For example ((100 good * 20 bad) / 5) = 400. Way out of 5!
If you need score up to five stars you will need to use ranges.
Calculate percentage between good and bad and then do an if checks.
For example:
$percentage = (($good - $bad) / $good) * 100;
if($percentage => 100) {
//5 starts
} else if ($percentage < 100 && $percentage => 80) {
//4 stars
} else if ($percentage < 80 && $percentage => 60) {
//3 stars
} else if ($pecentage < 60 && $percentage => 40) {
//2 starts
} else {
//1 star
}
That's just a basic example. There are different ways to approach this. You need to adjust it to your needs and try if it works for you.
I did this really quick, so didn't test it. Please, check and see if it fits you. I just wanted to give you an idea.

How do I calculate the answer of a exponential formula?

we have to make a web game for a school project.
but im currently stuck at one point. its a mafia styled web game, you probably know one of these. When your charachter goes to the hospital to get his wounds fixed up he needs to pay a certain amount of money. this is calculated by the following code
$maxHeal = 100 - $health;
$costs =round(pow($maxHeal,1.8));
health is a number between 0 and 100 and the costs are based on exponential growth. but if the player can only afford 50 but types in 100, how do I make sure he only getw 50, and how do I make sure it are the first 50 health points, the most expensive ones and not the cheap ones, this will cause player to just type in 1 press enter to get some cheap health.
I hope my porblem is clear, if you have any questions about other parts of the codes please ask
thanks in advance
edit: to give some extra clearance,
when I am at 10 health(hp) and I want to go back to 100hp I need to get a 90 extra. there is a form where I can type how much hp I want to cure, so I type in 90 and the system requests to ad 90 to my life so it makes 100. to do this I need to check if the players can afford to pay for those 90 points. if I can not pay for 90 but can pay for 50 I want those 50 to be added anyways. but if I count from 1 to 50 and to one form 40(the remaining I need to heal another timer) it wil cost less than counting from 1 to 90 because of the exponential growth.
so I need 2 checks. I have to cure al I can afford, so if I can afford just 50 of the 90 hp I need, I will only get 50 points and pay for 50, but as this wil be cheaper how can I make sure that I pay for the 50 like I woulld pay for 90. so 50 and 40 need to be equal to one times 90
Based on your question (which is not totally clear to me, but hey, I'm in a good mood), I built the following example:
//total amount of health points
$points = 20000;
//health left
$health = 10;
//how many health do we miss? 100 = maximal
$maxHeal = 100 - $health;
//counter
$i = 0;
while($points > $cost = round(pow($maxHeal-$i,1.8))) {
//check if the user has enough points
if ($points - $cost > 0) {
$health++;
echo "Healt +1 point, total: " . $health . " (points " . $points . " - cost " . $cost . " = " . ($points - $cost) . " left)" . "\n";
} else {
echo "Can't heal anymore, not enough points left (" . $points . ")" . "\n";
}
$points -= $cost;
$i++;
}
echo "\n";
echo "Remaining points: " . $points . ", needs points for next repair: " . $cost;
With the following output:
Health now: 10
Healt +1 point, total: 11 (points 20000 - cost 3293 = 16707 left)
Healt +1 point, total: 12 (points 16707 - cost 3228 = 13479 left)
Healt +1 point, total: 13 (points 13479 - cost 3163 = 10316 left)
Healt +1 point, total: 14 (points 10316 - cost 3098 = 7218 left)
Healt +1 point, total: 15 (points 7218 - cost 3035 = 4183 left)
Healt +1 point, total: 16 (points 4183 - cost 2971 = 1212 left)
Remaining points: 1212, needs points for next repair: 2909
I hope this gets you going :)

Probability Calculation

I have something like this in my website: There are grids, members click them randomly, they view a webpage, then they learn if they won a prize or not. They have limited number of chance daily.
My algorithm to calculate prize win probability:
Randomly select a number between 1 and 10,000
1a. if this number equals to 1 member wins X
1b. if this number =< 5 member wins Y etc.
Is there another way to calculate this or should I control prizes with additional codes (for example: if today x member won y amount prize stop giving prizes)?
Thanks.
Yes, there are several other ways to calculate this, but your idea is good enough. You can use the following pseudocode for assistance also:
int randomnumber = generaterandomnumber();
bool allprizesgone = getinformationfromdatabase();
if ( allprizesgone equals false ) {
if(randomnumber equals 1) {
member wins X
if(checkifallprizesfortodayaretakes() equals true) {
setinformationtodatabase(allprizesgonetrue);
}
} else if (randomnumer is smaller than 5 ){ //because of else if members can't get both prizes
member wins Y
if(checkifallprizesfortodayaretakes() equals true) {
setinformationtodatabase(allprizesgonetrue);
}
}
}

Sorting data in PHP for a single elimination tournament display in HTML

I have a table that has the following columns and fields:
userid round faceoff username
------------------------------
1 1 2 Kevin
3 1 1 Steve
4 1 3 Jake
9 1 4 Sam
1 2 1 Kevin
9 2 2 Sam
1 3 1 Kevin
The round are the columns and faceoff are the rows. Thus round 1 has a max of faceoff 4, and round 2 has a faceoff max of 2, etc.
I want to display the data on users screens like so (basic HTML):
Round 1 Round 2 Final (round 3)
Steve
Kevin
Kevin
Kevin
Jake
Sam
Sam
Here is what I have so far:
$tor is the array from MySQL, I var_dump() it and everything is there. I'm just having issues with the for loops:
for ($u=0;$u<=$torindex;$u++)
{
for ($r=1;$r<=$torindex+1;$r++)
{
if ($tor[$u]['round'] == $r)
{
for ($f=1;$f<=$torindex+1;$f++)
{
if ($tor[$u]['faceoff'] == $f) $placement[$r][$f] = $tor[$u]['userid'].":".$tor[$u]['username'];
}
}
}
}
Where do I go from here?
For each row in your data table, you can find right row in HTML table to display it using this equation:
rowNum = pow(2, round - 1) + (faceoff - 1) * pow(2, round);
so this should work in MySQL:
SELECT * FROM tournament ORDER BY pow(2, round - 1) + (faceoff - 1) * pow(2, round);
Structure
I have used the Knockout tournament scheduler class by Nicholas Mossor Rathmann for this task in the past with great success. Given teams/players it will calculate the ties and eliminations based on the matches final score.
Output
For CSS/HTML output instead of the GD generated image the class gives you I used One Fork's jQuery & JSON to draw single-elimination tournament bracket with some modifications for IE compatibility.
Sort it by round like you have it and as you cycle through the rows keep track of the current round. If the row's round is not equal to the current round you know to move to the right. You can close and start a div or ul and float them to the left.
http://jsfiddle.net/RxDrd/

php game, formula to calculate a level based on exp

Im making a browser based PHP game and in my database for the players it has a record of that players total EXP or experience.
What i need is a formula to translate that exp into a level or rank, out of 100.
So they start off at level 1, and when they hit say, 50 exp, go to level 2, then when they hit maybe 125/150, level 2.
Basically a formula that steadily makes each level longer (more exp)
Can anyone help? I'm not very good at maths :P
Many formulas may suit your needs, depending on how fast you want the required exp to go up.
In fact, you really should make this configurable (or at least easily changed in one central location), so that you can balance the game later. In most games these (and other) formulas are determined only after playtesting and trying out several options.
Here's one formula: First level-up happens at 50 exp; second at 150exp; third at 300 exp; fourth at 500 exp; etc. In other words, first you have to gather 50 exp, then 100 exp, then 150exp, etc. It's an Arithmetic Progression.
For levelup X then you need 25*X*(1+X) exp.
Added: To get it the other way round you just use basic math. Like this:
y=25*X*(1+X)
0=25*X*X+25*X-y
That's a standard Quadratic equation, and you can solve for X with:
X = (-25Âħsqrt(625+100y))/50
Now, since we want both X and Y to be greater than 0, we can drop one of the answers and are left with:
X = (sqrt(625+100y)-25)/50
So, for example, if we have 300 exp, we see that:
(sqrt(625+100*300)-25)/50 = (sqrt(30625)-25)/50 = (175-25)/50 = 150/50 = 3
Now, this is the 3rd levelup, so that means level 4.
If you wanted the following:
Level 1 # 0 points
Level 2 # 50 points
Level 3 # 150 points
Level 4 # 300 points
Level 5 # 500 points etc.
An equation relating experience (X) with level (L) is:
X = 25 * L * L - 25 * L
To calculate the level for a given experience use the quadratic equation to get:
L = (25 + sqrt(25 * 25 - 4 * 25 * (-X) ))/ (2 * 25)
This simplifies to:
L = (25 + sqrt(625 + 100 * X)) / 50
Then round down using the floor function to get your final formula:
L = floor(25 + sqrt(625 + 100 * X)) / 50
Where L is the level, and X is the experience points
It really depends on how you want the exp to scale for each level.
Let's say
LvL1 : 50 Xp
Lvl2: LvL1*2=100Xp
LvL3: LvL2*2=200Xp
Lvl4: LvL3*2=400Xp
This means you have a geometric progression
The Xp required to complete level n would be
`XPn=base*Q^(n-1)`
In my example base is the inital 50 xp and Q is 2 (ratio).
Provided a player starts at lvl1 with no xp:
when he dings lvl2 he would have 50 total Xp
at lvl3 150xp
at lvl4 350xp
and so forth
The total xp a player has when he gets a new level up would be:
base*(Q^n-1)/(Q-1)
In your case you already know how much xp the player has. For a ratio of 2 the formula gets simpler:
base * (2^n-1)=total xp at level n
to find out the level for a given xp amount all you need to do is apply a simple formula
$playerLevel=floor(log($playerXp/50+1,2));
But with a geometric progression it will get harder and harder and harder for players to level.
To display the XP required for next level you can just calculate total XP for next level.
$totalXpNextLevel=50*(pow(2,$playerLevel+1)-1);
$reqXp=$totalXpNextLevel - $playerXp;
Check start of the post:
to get from lvl1 -> lvl2 you need 50 xp
lvl2 ->lvl3 100xp
to get from lvl x to lvl(x+1)
you would need
$totalXprequired=50*pow(2,$playerLevel-1);
Google gave me this:
function experience($L) {
$a=0;
for($x=1; $x<$L; $x++) {
$a += floor($x+300*pow(2, ($x/7)));
}
return floor($a/4);
}
for($L=1;$L<100;$L++) {
echo 'Level '.$L.': '.experience($L).'<br />';
}
It is supposed the be the formula that RuneScape uses, you might me able to modify it to your needs.
Example output:
Level 1: 0
Level 2: 55
Level 3: 116
Level 4: 184
Level 5: 259
Level 6: 343
Level 7: 435
Level 8: 536
Level 9: 649
Level 10: 773
Here is a fast solution I used for a similar problem. You will likely wanna change the math of course, but it will give you the level from a summed xp.
$n = -1;
$L = 0;
while($n < $xp){
$n += pow(($L+1),3)+30*pow(($L+1),2)+30*($L+1)-50;
$L++;
}
echo("Current XP: " .$xp);
echo("Current Level: ".$L);
echo("Next Level: " .$n);
I take it what you're looking for is the amount of experience to decide what level they are on? Such as:
Level 1: 50exp
Level 2: 100exp
Level 3: 150exp ?
if that's the case you could use a loop something like:
$currentExp = x;
$currentLevel;
$i; // initialLevel
for($i=1; $i < 100; $i *= 3)
{
if( ($i*50 > $currentExp) && ($i < ($i+1)*$currentExp)){
$currentLevel = $i/3;
break;
}
}
This is as simple as I can make an algorithm for levels, I haven't tested it so there could be errors.
Let me know if you do use this, cool to think an algorithm I wrote could be in a game!
The original was based upon a base of 50, thus the 25 scattered across the equation.
This is the answer as a real equation. Just supply your multiplier (base) and your in business.
$_level = floor( floor( ($_multipliter/2)
+ sqrt( ($_multipliter^2) + ( ($_multipliter*2) * $_score) )
)
/ $_multipliter
) ;

Categories