|
@@ -1104,19 +1104,20 @@ function validateCompany(source) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private function benford_form($edit = false) {
|
|
private function benford_form($edit = false) {
|
|
|
- if (!($field = V::get('_benfordField', '', $_GET))) throw new Exception ("Błąd konfiguracji UrlAction - brak parametru _benfordField (DANE )");
|
|
|
|
|
|
|
+ if (!($valueField = V::get('_benfordValueField', '', $_GET))) throw new Exception ("Błąd konfiguracji UrlAction - brak parametru _benfordField (DANE )");
|
|
|
|
|
+ $groupField = V::get('_benfordGroupField', '', $_GET);
|
|
|
if (!($namespace = V::get('_fromNamespace', '', $_GET))) throw new Exception("Błąd formularza");
|
|
if (!($namespace = V::get('_fromNamespace', '', $_GET))) throw new Exception("Błąd formularza");
|
|
|
|
|
|
|
|
Lib::loadClass('FeatureAttrSelected');
|
|
Lib::loadClass('FeatureAttrSelected');
|
|
|
$count = FeatureAttrSelected::getTotalSelected($namespace);
|
|
$count = FeatureAttrSelected::getTotalSelected($namespace);
|
|
|
$selectedTable = FeatureAttrSelected::getAttributeTableName($namespace, User::getID());
|
|
$selectedTable = FeatureAttrSelected::getAttributeTableName($namespace, User::getID());
|
|
|
- $query = "select `t`.`ID`, `{$field}` from `{$this->SOURCE['TABLE']}` `t` join `{$selectedTable}` `s` on `t`.`ID` = `s`.`primaryKey` where `t`.`{$field}` != 0 order by `s`.`primaryKey`";
|
|
|
|
|
|
|
+ $query = "select `t`.`ID`, `{$valueField}` from `{$this->SOURCE['TABLE']}` `t` join `{$selectedTable}` `s` on `t`.`ID` = `s`.`primaryKey` where `t`.`{$valueField}` != 0 order by `s`.`primaryKey`";
|
|
|
$values = [];
|
|
$values = [];
|
|
|
try {
|
|
try {
|
|
|
$result = DB::getPDO()->fetchAll($query);
|
|
$result = DB::getPDO()->fetchAll($query);
|
|
|
- foreach ($result as $row) $values[$row['ID']] = $row[$field];
|
|
|
|
|
|
|
+ foreach ($result as $row) $values[$row['ID']] = $row[$valueField];
|
|
|
} catch (Exception $e) {
|
|
} catch (Exception $e) {
|
|
|
- echo $e->getMessage();
|
|
|
|
|
|
|
+ throw new Exception("Błąd zapytania SQL ({$e->getMessage()})");
|
|
|
}
|
|
}
|
|
|
if (!$values) throw new Exception("Nie wybrano żadnych obiektów lub wszystkie wybrane obiekty mają zerową wartość");
|
|
if (!$values) throw new Exception("Nie wybrano żadnych obiektów lub wszystkie wybrane obiekty mają zerową wartość");
|
|
|
|
|
|
|
@@ -1136,7 +1137,7 @@ function validateCompany(source) {
|
|
|
</legend>
|
|
</legend>
|
|
|
<div class="form-group">
|
|
<div class="form-group">
|
|
|
<div class="col-sm-12">
|
|
<div class="col-sm-12">
|
|
|
- <h5>Analiza na podstawie kolumny <?=$field?>. Liczba znalezionych obiektów z niezerową wartością: <?=count($values)?> (wybrano obiektów: <?=$count?>)</h5>
|
|
|
|
|
|
|
+ <h5>Analiza na podstawie kolumny <?=$valueField?>. Liczba znalezionych obiektów z niezerową wartością: <?=count($values)?> (wybrano obiektów: <?=$count?>)</h5>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<?php if($edit):?>
|
|
<?php if($edit):?>
|
|
@@ -1173,6 +1174,7 @@ function validateCompany(source) {
|
|
|
<td style="vertical-align:middle;" rowspan="2">Liczba wystąpień</td>
|
|
<td style="vertical-align:middle;" rowspan="2">Liczba wystąpień</td>
|
|
|
<td style="vertical-align:middle;" rowspan="2">Procent występowania</td>
|
|
<td style="vertical-align:middle;" rowspan="2">Procent występowania</td>
|
|
|
<td colspan="3">Rozkład Benford'a</td>
|
|
<td colspan="3">Rozkład Benford'a</td>
|
|
|
|
|
+ <td style="vertical-align:middle;" rowspan="2">Szczegóły</td>
|
|
|
<?php if($edit):?>
|
|
<?php if($edit):?>
|
|
|
<td style="vertical-align:middle;" rowspan="2">Załącz obiekty<br/>do raportu</td>
|
|
<td style="vertical-align:middle;" rowspan="2">Załącz obiekty<br/>do raportu</td>
|
|
|
<?php endif;?>
|
|
<?php endif;?>
|
|
@@ -1189,14 +1191,45 @@ function validateCompany(source) {
|
|
|
return number_format($n, 3, ',', '');
|
|
return number_format($n, 3, ',', '');
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ $genShowDetails = function($a, $groupField) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (!$groupField) throw new Exception("Brak konfiguracji kolumny grupującej");
|
|
|
|
|
+ $tempTable = uniqid('_temp_benford_ids_');
|
|
|
|
|
+ DB::getPDO()->query("create temporary table `{$tempTable}` (`ID` int(11) NOT NULL, UNIQUE KEY `ID` (`ID`))");
|
|
|
|
|
+ foreach (array_chunk($a, 100) as $ids) {
|
|
|
|
|
+ DB::getPDO()->query("insert into `{$tempTable}` values (" . implode('),(', $ids) . ")");
|
|
|
|
|
+ }
|
|
|
|
|
+ $query = "select `table`.`{$groupField}` as `field`, count(*) as `count` from `{$this->SOURCE['TABLE']}` `table` join `{$tempTable}` `temp` on `table`.`ID` = `temp`.`ID` where coalesce(`table`.`{$groupField}`,'') != '' group by `table`.`{$groupField}` having `count` > 1 order by `count` desc limit 10";
|
|
|
|
|
+ try {
|
|
|
|
|
+ $result = DB::getPDO()->fetchAll($query);
|
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
|
+ throw new Exception("Nieznany błąd, prawdopodobnie błędna konfiguracja kolumny grupującej");
|
|
|
|
|
+ }
|
|
|
|
|
+ $showDetails = "<h4>Najczęściej występujące wartości kolumny {$groupField}</h4>";
|
|
|
|
|
+ if ($result) {
|
|
|
|
|
+ $showDetails .= "<table class=\"table table-bordered table-hover table-striped table-condensed\"><thead><tr style=\"font-weight:bold;\"><td>Wartość</td><td>Liczba wystąpień</td></tr></thead><tbody>";
|
|
|
|
|
+ $showDetails .= implode('', array_map(function($v) {
|
|
|
|
|
+ return "<tr><td>{$v['field']}</td><td>{$v['count']}</td></tr>";
|
|
|
|
|
+ }, $result));
|
|
|
|
|
+ $showDetails .= "</tbody></table>";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $showDetails .= "<h5>Żadna wartość nie występuje wiele razy</h5>";
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
|
+ $showDetails = $e->getMessage();
|
|
|
|
|
+ }
|
|
|
|
|
+ return $showDetails;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
for ($ka = 1; $ka < 10; $ka++) {
|
|
for ($ka = 1; $ka < 10; $ka++) {
|
|
|
if (!isset($benford['firstStage'][$ka])) $benford['firstStage'][$ka] = ['count' => 0, 'value' => 0, 'correct' => true];
|
|
if (!isset($benford['firstStage'][$ka])) $benford['firstStage'][$ka] = ['count' => 0, 'value' => 0, 'correct' => true];
|
|
|
$va = $benford['firstStage'][$ka];
|
|
$va = $benford['firstStage'][$ka];
|
|
|
$odchylenie = round(($va['value'] / Benford::benford($ka) - 1) * 100, 3);
|
|
$odchylenie = round(($va['value'] / Benford::benford($ka) - 1) * 100, 3);
|
|
|
if ($odchylenie > 0) $odchylenie = "+" . $number_format($odchylenie);
|
|
if ($odchylenie > 0) $odchylenie = "+" . $number_format($odchylenie);
|
|
|
else $odchylenie = $number_format($odchylenie);
|
|
else $odchylenie = $number_format($odchylenie);
|
|
|
|
|
+ if (!$va['correct']) $showDetails = $genShowDetails($va['keys'], $groupField);
|
|
|
?>
|
|
?>
|
|
|
- <tr style="text-align:center; font-weight:bold;" class="tr-stage1-<?=$va['correct'] ? 'green' : 'red" onClick="toggleSecondStage(' . $ka . ');'?>">
|
|
|
|
|
|
|
+ <tr style="text-align:center; font-weight:bold;<?=$va['correct'] ? '' : ' cursor:pointer;'?>" class="tr-stage1-<?=$va['correct'] ? 'green' : 'red" onClick="toggleSecondStage(' . $ka . ');'?>">
|
|
|
<td style="text-align:left"><?=$ka?></td>
|
|
<td style="text-align:left"><?=$ka?></td>
|
|
|
<td>I</td>
|
|
<td>I</td>
|
|
|
<td style="text-align:right"><?=$va['count']?></td>
|
|
<td style="text-align:right"><?=$va['count']?></td>
|
|
@@ -1204,8 +1237,9 @@ function validateCompany(source) {
|
|
|
<td style="text-align:right"><?=$number_format(round(Benford::benford($ka) * 100, 3))?></td>
|
|
<td style="text-align:right"><?=$number_format(round(Benford::benford($ka) * 100, 3))?></td>
|
|
|
<td style="text-align:right"><?=$odchylenie?></td>
|
|
<td style="text-align:right"><?=$odchylenie?></td>
|
|
|
<td<?=$va['correct'] ? '' : ' name="firstStageDesc" data-ka="' . $ka . '"'?> nowrap><?=$va['correct'] ? 'Tak' : 'Nie (rozwiń)'?></td>
|
|
<td<?=$va['correct'] ? '' : ' name="firstStageDesc" data-ka="' . $ka . '"'?> nowrap><?=$va['correct'] ? 'Tak' : 'Nie (rozwiń)'?></td>
|
|
|
|
|
+ <td<?=$va['correct'] ? '>' : ' onClick="showAlert(\''. htmlentities($showDetails, ENT_QUOTES) .'\')"><span class="glyphicon glyphicon-search"></span>'?></td>
|
|
|
<?php if($edit):?>
|
|
<?php if($edit):?>
|
|
|
- <td><input type="checkbox" <?=$va['correct'] ? 'disabled' : 'checked name="checkFirstStage[]" value="' . $ka . '" onClick="toggleSecondStage(' . $ka . '); toggleCheckFirst(this)"'?>></td>
|
|
|
|
|
|
|
+ <td<?=$va['correct'] ? '' : ' onClick="_click(\'checkFirstStage_' . $ka . '\')"'?>><input type="checkbox" <?=$va['correct'] ? 'disabled' : 'checked id="checkFirstStage_' . $ka . '" name="checkFirstStage[]" value="' . $ka . '" onClick="toggleCheckFirst(this)"'?>></td>
|
|
|
<?php endif;?>
|
|
<?php endif;?>
|
|
|
</tr>
|
|
</tr>
|
|
|
<?php
|
|
<?php
|
|
@@ -1216,6 +1250,7 @@ function validateCompany(source) {
|
|
|
$odchylenie = round(($vb['value'] / Benford::benford($ka * 10 + $kb) - 1) * 100, 3);
|
|
$odchylenie = round(($vb['value'] / Benford::benford($ka * 10 + $kb) - 1) * 100, 3);
|
|
|
if ($odchylenie > 0) $odchylenie = "+" . $number_format($odchylenie);
|
|
if ($odchylenie > 0) $odchylenie = "+" . $number_format($odchylenie);
|
|
|
else $odchylenie = $number_format($odchylenie);
|
|
else $odchylenie = $number_format($odchylenie);
|
|
|
|
|
+ if (!$vb['correct']) $showDetails = $genShowDetails($vb['keys'], $groupField);
|
|
|
?>
|
|
?>
|
|
|
<tr style="text-align:center;" class="tr-stage2-<?=$vb['correct'] ? 'green' : 'red'?>" name="secondStage" data-ka="<?=$ka?>" hidden>
|
|
<tr style="text-align:center;" class="tr-stage2-<?=$vb['correct'] ? 'green' : 'red'?>" name="secondStage" data-ka="<?=$ka?>" hidden>
|
|
|
<td style="text-align:left"><?=$ka . $kb?></td>
|
|
<td style="text-align:left"><?=$ka . $kb?></td>
|
|
@@ -1225,8 +1260,9 @@ function validateCompany(source) {
|
|
|
<td style="text-align:right"><?=$number_format(round(Benford::benford($ka * 10 + $kb) * 100, 3))?></td>
|
|
<td style="text-align:right"><?=$number_format(round(Benford::benford($ka * 10 + $kb) * 100, 3))?></td>
|
|
|
<td style="text-align:right"><?=$odchylenie?></td>
|
|
<td style="text-align:right"><?=$odchylenie?></td>
|
|
|
<td><?=$vb['correct'] ? 'Tak' : 'Nie'?></td>
|
|
<td><?=$vb['correct'] ? 'Tak' : 'Nie'?></td>
|
|
|
|
|
+ <td<?=$vb['correct'] ? '>' : ' style="cursor:pointer;" onClick="showAlert(\''. htmlentities($showDetails, ENT_QUOTES) .'\')"><span class="glyphicon glyphicon-search"></span>'?></td>
|
|
|
<?php if($edit):?>
|
|
<?php if($edit):?>
|
|
|
- <td onClick=""><input type="checkbox"<?=$vb['correct'] ?: ' checked name="checkSecondStage[]" value="' . $ka . $kb . '" onClick="toggleCheckSecond(this)"'?> disabled></td>
|
|
|
|
|
|
|
+ <td<?=$vb['correct'] ? '' : ' style="cursor:pointer;" onClick="_click(\'checkSecondStage_' . $ka . $kb . '\')"'?>><input type="checkbox"<?=$vb['correct'] ?: ' checked id="checkSecondStage_' . $ka . $kb . '" name="checkSecondStage[]" value="' . $ka . $kb . '" onClick="toggleCheckSecond(this)"'?> disabled></td>
|
|
|
<?php endif;?>
|
|
<?php endif;?>
|
|
|
</tr>
|
|
</tr>
|
|
|
<?php
|
|
<?php
|
|
@@ -1236,11 +1272,13 @@ function validateCompany(source) {
|
|
|
?>
|
|
?>
|
|
|
</tbody>
|
|
</tbody>
|
|
|
</table>
|
|
</table>
|
|
|
-</div>
|
|
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</form>
|
|
</form>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+<div id="alert" onClick="hideAlert()">
|
|
|
|
|
+ <div id="alertMsg"></div>
|
|
|
|
|
+</div>
|
|
|
<style type="text/css">
|
|
<style type="text/css">
|
|
|
<!--
|
|
<!--
|
|
|
#benford .tr-stage1-green,.tr-stage1-red {font-weight:bold;}
|
|
#benford .tr-stage1-green,.tr-stage1-red {font-weight:bold;}
|
|
@@ -1248,10 +1286,25 @@ function validateCompany(source) {
|
|
|
#benford .tr-stage1-red,.tr-stage2-red {color:#ff0000;}
|
|
#benford .tr-stage1-red,.tr-stage2-red {color:#ff0000;}
|
|
|
body { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;}
|
|
body { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;}
|
|
|
::selection {background: transparent;}
|
|
::selection {background: transparent;}
|
|
|
|
|
+#alert {display:none; position: fixed; left: 0; top: 0; width: 100%; height: 100%; text-align: center; z-index: 1000; background-color: rgba(0,0,0,0.5);}
|
|
|
|
|
+#alert div {width: 500px; height: auto; margin: 200px auto; background: #fff; padding: 10px; text-align: center; overflow: hidden;}
|
|
|
-->
|
|
-->
|
|
|
</style>
|
|
</style>
|
|
|
|
|
+<script src="static/sweetalert2.min.js"></script>
|
|
|
<script language="JavaScript">
|
|
<script language="JavaScript">
|
|
|
<!--
|
|
<!--
|
|
|
|
|
+function showAlert(s) {
|
|
|
|
|
+ event.stopPropagation();
|
|
|
|
|
+ document.getElementById('alertMsg').innerHTML = s;
|
|
|
|
|
+ document.getElementById('alert').style.display = 'block';
|
|
|
|
|
+}
|
|
|
|
|
+function hideAlert() {
|
|
|
|
|
+ document.getElementById('alert').style.display = 'none';
|
|
|
|
|
+}
|
|
|
|
|
+function _click(id) {
|
|
|
|
|
+ event.stopPropagation();
|
|
|
|
|
+ document.getElementById(id).click();
|
|
|
|
|
+}
|
|
|
function toggleSecondStage(ka) {
|
|
function toggleSecondStage(ka) {
|
|
|
var rows = document.getElementsByName('secondStage');
|
|
var rows = document.getElementsByName('secondStage');
|
|
|
var hidden = false;
|
|
var hidden = false;
|
|
@@ -1301,12 +1354,14 @@ function toggleStage(option) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
function toggleCheckFirst(check) {
|
|
function toggleCheckFirst(check) {
|
|
|
|
|
+ event.stopPropagation();
|
|
|
var checks = document.getElementsByName('checkSecondStage[]');
|
|
var checks = document.getElementsByName('checkSecondStage[]');
|
|
|
for(var i = 0, n = checks.length; i < n; i++) {
|
|
for(var i = 0, n = checks.length; i < n; i++) {
|
|
|
if ((checks[i].value / 10 | 0) == check.value) checks[i].checked = check.checked;
|
|
if ((checks[i].value / 10 | 0) == check.value) checks[i].checked = check.checked;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
function toggleCheckSecond(check) {
|
|
function toggleCheckSecond(check) {
|
|
|
|
|
+ event.stopPropagation();
|
|
|
var checks = document.getElementsByName('checkSecondStage[]');
|
|
var checks = document.getElementsByName('checkSecondStage[]');
|
|
|
var all = true;
|
|
var all = true;
|
|
|
var ka = check.value / 10 | 0;
|
|
var ka = check.value / 10 | 0;
|