summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--web/index.html39
-rw-r--r--web/osika.css97
-rw-r--r--web/osika.js52
-rw-r--r--web/osika.php282
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">&spades;</span>
+ <input type="text" id="suit0" value="xxxx" />
+ <span class="hearts">&hearts;</span>
+ <input type="text" id="suit1" value="xxx" />
+ <span class="diamonds">&diams;</span>
+ <input type="text" id="suit2" value="xxx" />
+ <span class="clubs">&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">&spades;</th><th class="hearts">&hearts;</th><th class="diamonds">&diams;</th><th class="clubs">&clubs;</th><th>&Sigma;</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