diff options
-rw-r--r-- | web/index.html | 39 | ||||
-rw-r--r-- | web/osika.css | 97 | ||||
-rw-r--r-- | web/osika.js | 52 | ||||
-rw-r--r-- | web/osika.php | 282 |
4 files changed, 470 insertions, 0 deletions
diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..c8a547c --- /dev/null +++ b/web/index.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>OSiKa</title> + <script src="http://code.jquery.com/jquery-1.4.3.js"></script> + <script src="osika.js"></script> + <link href="osika.css" rel="stylesheet" type="text/css" /> + </head> + <body> + <form name="osika"> + <h1>OSiKa</h1> + Podaj rękę do oceny:<br /> + <span class="spades">♠</span> + <input type="text" id="suit0" value="xxxx" /> + <span class="hearts">♥</span> + <input type="text" id="suit1" value="xxx" /> + <span class="diamonds">♦</span> + <input type="text" id="suit2" value="xxx" /> + <span class="clubs">♣</span> + <input type="text" id="suit3" value="xxx" /><br /> + <input type="submit" id="evaluate" value="Oceń" /> + <div id="result"></div> + </form> + <form> + Poprawność danych w formularzu: + <ul> + <li>ignorowane są białe znaki</li> + <li>wielkość liter nie ma znaczenia</li> + <li>ręka musi zawierać 13 kart</li> + <li><b>x</b> oznacza dowolną blotkę (ale cyfry również dozwolone)</li> + <li>Dama = Q/D, Walet = J/W, 10 = 10/T</li> + <li>w pojedynczym kolorze nie mogą duplikować się honory ani 9</li> + <li>kolejność kart w kolorze nie ma znaczenia</li> + <li>blotki nie są weryfikowane (kolor może posiadać zduplikowane blotki, może też posiadać niemożliwą liczbę blotek, np. 10)</li> + </ul> + </form> + </body> +</html> diff --git a/web/osika.css b/web/osika.css new file mode 100644 index 0000000..23ff631 --- /dev/null +++ b/web/osika.css @@ -0,0 +1,97 @@ +body { + background-color: #008200; + font-family: Georgia, Verdana, Helvetica, Arial, Sans Serif; +} + +h1 { + padding: 0; + margin: 0; + text-align: center; + font-family: Verdana; + color: #00340A; +} + +form { + margin: auto; + margin-bottom: 15px; + width: 750px; + border-radius: 5px; + border: solid 2px #DFFFFF; + text-align: center; + color: #DFFFFF; + background-color: #888; +} + +ul { + text-align: left; +} + +input { + width: 150px; + background-color: #00A600; + border: solid 2px #DFFFFF; + color: #DFFFFF; +} + +.spades { + color: darkblue; + font-size: 20px; +} + +.hearts { + color: red; + font-size: 20px; +} + +.diamonds { + color: orange; + font-size: 20px; +} + +.clubs { + color: darkgreen; + font-size: 20px; +} + +.error { + background-color: #880000; + color: red; + border-radius: 5px; + border: solid 2px red; +} + +th { + background-color: #666; + text-align: center; +} + +td { + text-align: right; + width: 80px; + line-height: 20px; +} + +td:first-child { + background-color: #666; + text-align: left; + width: 300px; +} + +.subtotal { + background-color: #777; + color: black; +} + +.total { + background-color: #666; + color: black; +} + +table { + width: 700px; + margin: auto; + margin-bottom: 10px; + margin-top: 10px; +} + + diff --git a/web/osika.js b/web/osika.js new file mode 100644 index 0000000..82fab72 --- /dev/null +++ b/web/osika.js @@ -0,0 +1,52 @@ +function getHand(hand) { + jQuery('#evaluate').val('Czekaj...'); + jQuery('#evaluate').attr('disabled', 'disabled'); + jQuery.getJSON( + 'osika.php', + { + 'h': hand, + 'f': 'json' + }, + function (data) { + jQuery('#evaluate').val('Oceń'); + jQuery('#evaluate').removeAttr('disabled'); + if (data.error) { + jQuery('#result').html('<div class="error">'+data.error+'</div>'); + } + else { + var html = '<table cellpadding="0" cellspacing="0"><tr><th></th><th class="spades">♠</th><th class="hearts">♥</th><th class="diamonds">♦</th><th class="clubs">♣</th><th>Σ</th></tr>'; + html += '<tr><td>Honory (lewy)</td><td>'+data.lh[0]+'</td><td>'+data.lh[1]+'</td><td>'+data.lh[2]+'</td><td>'+data.lh[3]+'</td><td class="subtotal">'+data.lh.total+'</td></tr>'; + html += '<tr><td>Poprawka za zgrupowania honorów</td><td>'+data.lh_plus[0]+'</td><td>'+data.lh_plus[1]+'</td><td>'+data.lh_plus[2]+'</td><td>'+data.lh_plus[3]+'</td><td class="subtotal">'+data.lh_plus.total+'</td></tr>'; + html += '<tr><td>Poprawka za podwiązania honorów</td><td>'+data.lh_10[0]+'</td><td>'+data.lh_10[1]+'</td><td>'+data.lh_10[2]+'</td><td>'+data.lh_10[3]+'</td><td class="subtotal">'+data.lh_10.total+'</td></tr>'; + html += '<tr><td>Poprawka za krótkie honory</td><td>'+data.lh_short[0]+'</td><td>'+data.lh_short[1]+'</td><td>'+data.lh_short[2]+'</td><td>'+data.lh_short[3]+'</td><td class="subtotal">'+data.lh_short.total+'</td></tr>'; + html += '<tr class="subtotal"><td>Lewy honorowe</td><td>'+(data.subtotal[0]-data.lu[0])+'</td><td>'+(data.subtotal[1]-data.lu[1])+'</td><td>'+(data.subtotal[2]-data.lu[2])+'</td><td>'+(data.subtotal[3]-data.lu[3])+'</td><td>'+(data.subtotal.total-data.lu.total)+'</td></tr>'; + html += '<tr><td>Lewy układowe</td><td>'+data.lu[0]+'</td><td>'+data.lu[1]+'</td><td>'+data.lu[2]+'</td><td>'+data.lu[3]+'</td><td class="subtotal">'+data.lu.total+'</td></tr>'; + html += '<tr class="subtotal"><td>Razem</td><td>'+data.subtotal[0]+'</td><td>'+data.subtotal[1]+'</td><td>'+data.subtotal[2]+'</td><td>'+data.subtotal[3]+'</td><td>'+data.subtotal.total+'</td></tr>'; + html += '<tr><td>Poprawka za lewy szybkie</td><td colspan="5">'+data.lsz.total+'</td></tr>'; + html += '<tr><td>Poprawka za wysokie blotki</td><td colspan="5">'+data.lu_plus.total+'</td></tr>'; + html += '<tr><td>Poprawka za kolory krótkie</td><td colspan="5">'+data.short_suit.total+'</td></tr>'; + html += '<tr><td>Poprawka za kolory starsze</td><td colspan="5">'+data.major_suit.total+'</td></tr>'; + html += '<tr><td>Poprawka za lokalizację</td><td colspan="5">'+data.l10n.total+'</td></tr>'; + html += '<tr class="total"><td>Łącznie</td><td colspan="5">'+data.total.total+'</td></tr>'; + html += '</table>'; + jQuery('#result').html(html); + location.hash = hand; + } + } + ); +} + +jQuery(document).ready(function () { + jQuery('#evaluate').click(function () { + var hand = jQuery('#suit0').val()+'|'+jQuery('#suit1').val()+'|'+jQuery('#suit2').val()+'|'+jQuery('#suit3').val(); + getHand(hand); + return false; + }); + if (location.hash) { + var hand = location.hash.substring(1).split('|'); + for (h = 0; h < hand.length; h++) { + jQuery('#suit'+h).val(hand[h]); + } + getHand(location.hash.substring(1)); + } +});
\ No newline at end of file diff --git a/web/osika.php b/web/osika.php new file mode 100644 index 0000000..092cc9c --- /dev/null +++ b/web/osika.php @@ -0,0 +1,282 @@ +<?php + +function suitSort($cardA, $cardB) { + if ($cardA == 'a') { + return -1; + } + if ($cardA == 'k') { + return ($cardB == 'a') ? 1 : -1; + } + if ($cardA == 'q') { + return (in_array($cardB, array('a', 'k'))) ? 1 : -1; + } + if ($cardA == 'j') { + return (in_array($cardB, array('a', 'k', 'q'))) ? 1 : -1; + } + if ($cardA == 't') { + return (in_array($cardB, array('a', 'k', 'q', 'j'))) ? 1 : -1; + } + if ($cardA == '9') { + return (in_array($cardB, array('a', 'k', 'q', 'j', 't'))) ? 1 : -1; + } + return 1; +} + +function sortHand(&$suit) { + $temp = str_split($suit); + usort($temp, 'suitSort'); + $suit = implode('', $temp); +} + +function honor($suit) { + $jack = 0; + if (strpos($suit, 'j') === 0) { + $jack = 0.125; + } + return substr_count($suit, 'a')*1.125+substr_count($suit, 'k')*0.8125+substr_count($suit, 'q')*0.4375+$jack; +} + +function honorPlus($suit) { + $dummy = array(); + $count = preg_match_all('/a|k|q|j/', $suit, $dummy); + if ($count < 2) { + return 0; + } + return $count*0.25; +} + +function honorShort($suit) { + $len = strlen($suit); + if (!$len || $len > 2) { + return 0; + } + $count = preg_match_all('/a|k|q|j/', $suit, $dummy); + if ($len == 1) { + return ($count)*(-0.125); + } + return $count*(-0.0625); +} + +function blot($length) { + if ($length < 4) { + return 0; + } + switch ($length) { + case 4: + return 0.4375; + case 5: + return 1.5; + case 6: + return 2.75; + case 7: + return 3.9375; + } + if ($length >= 8) { + return $length - 3; + } +} + +function blotPlus($suit) { + $dummy = array(); + return 0.125*((strlen($suit) > 3) && substr_count($suit, 't') && preg_match_all('/a|k|q/', $suit, $dummy))+(substr_count($suit, 't9'))*0.0625; +} + +function quickTricks($hand) { + $hand = '|'.$hand; + $high = substr_count($hand, 'a')+substr_count($hand, 'k'); + $low = substr_count($hand, 'q')+substr_count($hand, 'j')-substr_count($hand, '|j'); + $diff = $high - $low; + if ($diff > 2) { + return 0.125; + } + if ($diff > 1) { + return 0.0625; + } + if ($diff < -2) { + return -0.125; + } + if ($diff < -1) { + return -0.0625; + } + return 0; +} + +function luBlots($hand) { + $nonshort = ''; + foreach ($hand as $suit) { + if (strlen($suit) >= 3) { + $nonshort .= $suit; + } + } + $dummy = array(); + $count = preg_match_all('/t|9/', $nonshort, $dummy)-1; + if ($count > 0) { + return 0.0625; + } + if ($count < 0) { + return -0.0625; + } + return 0; +} + +function shortSuit($distribution) { + $suits = array(); + foreach ($distribution as $suit) { + if ($suit <= 3) { + $suits[] = $suit; + } + } + if (count($suits) < 2) { + return 0; + } + sort($suits); + $diff = $suits[1] - $suits[0]; + return ($diff > 1) ? 0.0625 : 0; +} + +function majorSuit($distribution) { + if ((($distribution[0] + $distribution[1]) >= 8) && ($distribution[0] > 2) && ($distribution[1] > 2)) { + return 0.0625; + } + return 0; +} + +function localization($distribution, $result) { + $strength = array(); + $length = array(); + foreach ($result['lh'] as $index => $value) { + if (is_numeric($index)) { + if ($distribution[$index] >= 3) { + if (isset($strength[$distribution[$index]])) { + $strength[$distribution[$index]] += ($result['lh'][$index]+$result['lh_plus'][$index]+$result['lh_10'][$index]+$result['lh_short'][$index]); + } + else { + $strength[$distribution[$index]] = ($result['lh'][$index]+$result['lh_plus'][$index]+$result['lh_10'][$index]+$result['lh_short'][$index]); + } + if (isset($length[$distribution[$index]])) { + $length[$distribution[$index]] += $distribution[$index]; + } + else { + $length[$distribution[$index]] = $distribution[$index]; + } + } + } + } + ksort($strength); + ksort($length); + $sumLength = array_sum($length); + $sumStrength = array_sum($strength); + $longestDiff = end($strength)-$sumStrength*end($length)/$sumLength; + $shortestDiff = reset($strength)-$sumStrength*reset($length)/$sumLength; + if (abs($longestDiff) > 0.5) { + if (abs($longestDiff) > 1) { + return 0.25*(abs($longestDiff)/$longestDiff); + } + else { + return 0.125*(abs($longestDiff)/$longestDiff); + } + } + if (abs($shortestDiff) > 0.5) { + if (abs($shortestDiff) > 1) { + return -0.125*(abs($shortestDiff)/$shortestDiff); + } + else { + return -0.0625*(abs($shortestDiff)/$shortestDiff); + } + } + return 0; +} + + +function osika($hand) { + if (!$hand) { + return array('error' => 'Brak podanej ręki!'); + } + $hand = strtolower($hand); + $hand = str_replace(array('10', 'w', 'd'), array('t', 'j', 'q'), $hand); + $hand = preg_replace('/\s/', '', $hand); + $suits = explode('|', $hand); + if (count($suits) != 4) { + return array('error' => 'Ręka nie zawiera 4 kolorów!'); + } + $distribution = array(); + $result = array('lu' => array('total' => 0), + 'lu_plus' => array('total' => 0), + 'lh' => array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 'total' => 0), + 'lh_plus' => array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 'total' => 0), + 'lh_10' => array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 'total' => 0), + 'lh_short' => array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 'total' => 0), + 'lsz' => array('total' => 0), + 'l10n' => array('total' => 0), + 'short_suit' => array('total' => 0), + 'major_suit' => array('total' => 0)); + foreach ($suits as $index => $suit) { + $distribution[] = strlen($suit); + if (preg_match('/[^akqjtx2-9]/', $suit)) { + return array('error' => 'Kolor '.$suit.' zawiera nieprawidłowe znaki!'); + } + foreach (array('a', 'k', 'q', 'j', 't', '9') as $honor) { + if (substr_count($suit, $honor) > 1) { + return array('error' => 'Kolor '.$suit.' zawiera zduplikowany honor!'); + } + } + sortHand($suit); + $result['lh_short'][$index] = honorShort($suit); + $result['lh_short']['total'] += $result['lh_short'][$index]; + $result['lh_10'][$index] = blotPlus($suit); + $result['lh_10']['total'] += $result['lh_10'][$index]; + $suit = substr($suit, 0, 3); + $result['lh'][$index] = honor($suit); + $result['lh']['total'] += $result['lh'][$index]; + $result['lh_plus'][$index] = honorPlus($suit); + $result['lh_plus']['total'] += $result['lh_plus'][$index]; + } + if (array_sum($distribution) != 13) { + return array('error' => 'Ręka nie zawiera 13 kart!'); + } + foreach ($distribution as $index => $suit) { + $result['lu'][$index] = blot($suit); + $result['lu']['total'] += $result['lu'][$index]; + } + $result['lsz']['total'] = quickTricks(implode('|',$suits)); + $result['lu_plus']['total'] = luBlots($suits); + $result['short_suit']['total'] = shortSuit($distribution); + $result['major_suit']['total'] = majorSuit($distribution); + $result['l10n']['total'] = localization($distribution, $result); + $subtotal = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 'total' => 0); + $total = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 'total' => 0); + foreach ($result as $i => $factor) { + if (count($factor) == 5) { + foreach ($factor as $index => $subt) { + $subtotal[$index] += $subt; + } + } + $total['total'] += $factor['total']; + } + $result['subtotal'] = $subtotal; + $result['total'] = $total; + return $result; +} + +$hand = $_REQUEST['h']; +$res = osika($hand); +if (!isset($_REQUEST['f'])) { + $_REQUEST['f'] = ''; +} +switch ($_REQUEST['f']) { + case 'json': + echo json_encode($res); + exit; + default: + if (isset($res['error'])) { + echo 'Błąd: '.$res['error']."\n"; + exit; + } + else { + print_r($res); + } +} + + + +?>
\ No newline at end of file |