Skip to content
Snippets Groups Projects
Commit 84a56f22 authored by Hakkel Tamás's avatar Hakkel Tamás
Browse files

burst grouping, error message on no image

parent 469627f5
No related branches found
No related tags found
No related merge requests found
Thumbs.db
.vscode/
*.sqlite
db-backup
images
\ No newline at end of file
images/
\ No newline at end of file
<?php
if ( ! isset($_SERVER['uid']) AND ! in_array($_SERVER['uid'],array('hakta','botcs'))) die('Permission denied');
// Tömörítőhöz kell
ob_start("ob_gzhandler");
// Header-ök
header('Vary: Accept-Encoding');
header('Pragma: no-cache');
header('Cache-Control: no-cache');
header('Accept-Ranges: bytes');
header('Content-Encoding: gzip');
$db = new PDO('sqlite:../db/db.sqlite');
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$result = $db->prepare('
SELECT name,shibboleth,s, w as waiting,a as accepted, r as rejected FROM
user
LEFT JOIN (
SELECT user_ID,count(*) s FROM suggestion GROUP BY user_ID
) USING(user_ID)
LEFT JOIN (
SELECT user_ID,count(*) w FROM suggestion LEFT JOIN annotation using(thumbnail_ID,user_ID) WHERE accepted IS NULL GROUP BY user_ID
) USING(user_ID)
LEFT JOIN (
SELECT user_ID,count(*) a FROM suggestion LEFT JOIN annotation using(thumbnail_ID,user_ID) WHERE accepted = 1 GROUP BY user_ID
) USING(user_ID)
LEFT JOIN (
SELECT user_ID,count(*) r FROM suggestion LEFT JOIN annotation using(thumbnail_ID,user_ID) WHERE accepted = 0 GROUP BY user_ID
) USING(user_ID)
ORDER BY name ASC
');
$result->execute();
$result = $result->fetchAll(PDO::FETCH_ASSOC);
?><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="PPKE ITK beléptető kapu">
<meta name="author" content="Hakkel Tamás">
<title>Sam</title>
<link rel="shortcut icon" href="../logo.ico">
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"
integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4"
crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Quicksand:400,500" rel="stylesheet">
<script defer src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ"
crossorigin="anonymous"></script>
<script defer src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm"
crossorigin="anonymous"></script>
<style>
body {
font-family: 'Quicksand', sans-serif;
font-weight: 300;
}
nav {
font-size: 25px;
box-shadow: 0px 3px 5px lightgrey;
font-weight: 500;
position: fixed;
}
#logo {
height: 2.5rem;
padding: 0rem 1rem 0rem 0rem;
}
</style>
</head>
<body>
<nav class="navbar fixed-top navbar-expand-sm navbar-light bg-light">
<a class="navbar-brand" href="#">
<img src="../logo.svg" width="30" height="30" class="d-inline-block align-top" alt="logo">
</a>
<div class="collapse navbar-collapse" id="navbarToggle">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="../">
<span class="text">Admin area</span>
<span class="text" style="display:none">Admin felület</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://users.itk.ppke.hu/~hakta/belepteto/selection/">
<span class="text">Selection</span>
<span class="text" style="display:none">Válogatás</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">
<span class="text">Profile</span>
<span class="text" style="display:none">Profil</span>
</a>
</li>
</ul>
</div>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</nav>
<div class="container" style="margin-top:6em">
<div class="row">
<div class="col-sm-10 offset-sm-1 col-lg-8 offset-lg-2">
<table class="table table-striped table-hover">
<thead class="thead-light">
<tr>
<th rowspan="2" style="vertical-align: middle;">Name</th>
<th rowspan="2" style="vertical-align: middle;">All</th>
<th colspan="3" style="text-align: center;">suggestion</th>
</tr>
<tr>
<th>Waiting</th>
<th>Accepted</th>
<th>Rejected</th>
</tr>
</thead>
<tbody>
<?php foreach ($result as $row): ?>
<tr>
<td><a href="https://users.itk.ppke.hu/~hakta/belepteto/selection/?<?=$row['shibboleth']?>" target="_blank"><?=$row['name']?></a></td>
<td><?=is_null($row['s']) ? 0 : $row['s']?></td>
<td><?=is_null($row['waiting']) ? 0 : $row['waiting']?></td>
<td><?=is_null($row['accepted']) ? 0 : $row['accepted']?></td>
<td><?=is_null($row['rejected']) ? 0 : $row['rejected']?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
<?php
// Csak bejelentkezettek
if ( ! isset($_SERVER['uid'])) die('Permission denied');
// Tömörítőhöz kell
ob_start("ob_gzhandler");
// Header-ök
header('Vary: Accept-Encoding');
header('Pragma: no-cache');
header('Cache-Control: no-cache');
header('Accept-Ranges: bytes');
header('Content-Encoding: gzip');
// Csabi és én hozzáférhetünk bárkinek a képeihez
// Only admins are allowed to edit other's annotations
if (isset($_POST['uid']) AND ($_SERVER['uid'] === 'hakta' OR $_SERVER['uid'] === 'botcs'))
$shibboleth = $_POST['uid'];
else
$shibboleth = $_SERVER['uid'];
// Ha már vannak betöltve képek, és szeretnénk, hogy csak olyanokat küldjünk, ami még nincs betöltve
// Once the page is loaded, we do not want to send already loaded images
if (isset($_POST['last_timestamp']))
$last_timestamp = (int)$_POST['last_timestamp'];
else
......@@ -27,25 +23,36 @@ else
$db = new PDO('sqlite:../db/db.sqlite');
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
// Mentés
if (isset($_POST['accepted']) AND isset($_POST['rejected'])) {
// Saving annotation
if (isset($_POST['accepted']) OR isset($_POST['rejected'])) {
$result = $db->prepare('SELECT user_ID FROM user WHERE shibboleth=:shibboleth');
$result->execute(array('shibboleth' => $shibboleth));
$result = $result->fetch(PDO::FETCH_ASSOC);
$user_ID = $result['user_ID'];
$accepted = implode(',',array_map('intval', $_POST['accepted']));
$limit = $db->exec("UPDATE annotation SET status='accepted' WHERE thumbnail_ID IN ($accepted) AND user_ID='$user_ID'");
$rejected = implode(',',array_map('intval', $_POST['rejected']));
$limit += $db->exec("UPDATE annotation SET status='rejected' WHERE thumbnail_ID IN ($rejected) AND user_ID='$user_ID'");
$limit = 100;
if (isset($_POST['accepted']))
foreach ($_POST['accepted'] as $thumbnail_ID)
$db->exec("
INSERT INTO annotation (thumbnail_ID,user_ID,accepted)
VALUES (".intval($thumbnail_ID).",$user_ID,1)");
if (isset($_POST['rejected']))
foreach ($_POST['rejected'] as $thumbnail_ID)
$db->exec("
INSERT INTO annotation (thumbnail_ID,user_ID,accepted)
VALUES (".intval($thumbnail_ID).",$user_ID,0)");
} else {
$limit = 1000;
$limit = 500;
}
// Képek lekérdezése
// Query for not annotated images
$query = '
SELECT thumbnail_ID,timestamp,path,thumbnail_path
FROM annotation JOIN thumbnail USING(thumbnail_ID) JOIN photo USING(photo_ID) JOIN user USING(user_ID)
WHERE shibboleth=:shibboleth AND status = "waiting" AND timestamp < :last_timestamp
SELECT thumbnail_ID,timestamp,path as photo_path,thumbnail_path,xmin,ymin,xmax,ymax
FROM suggestion
JOIN thumbnail USING(thumbnail_ID) JOIN photo USING(photo_ID)
JOIN user USING(user_ID)
WHERE shibboleth=:shibboleth
AND thumbnail_ID NOT IN (SELECT thumbnail_ID FROM annotation JOIN user USING(user_ID) WHERE shibboleth=:shibboleth)
AND timestamp < :last_timestamp
GROUP BY thumbnail_ID
ORDER BY timestamp ASC
LIMIT :limit
......@@ -58,63 +65,103 @@ $result->execute(array(
));
$result = $result->fetchAll(PDO::FETCH_ASSOC);
// Előkészületek a lenti ciklushoz
$path_part_to_remove = '/home/csbotos/video/';
$path_part_to_remove_length = strlen($path_part_to_remove);
$answer = array();
$previous_timestamp = -1;
$group_key = "";
// Localization
$hungarian = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) === 'hu';
$groupping_time = 10000;
$month = $hungarian ?
array('','Jan','Feb','Már','Ápr','Máj','Jún','Júl','Aug','Szep','Okt','Nov','Dec') :
array('','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
$day = $hungarian ?
array('','Hé','Ke','Sze','Csüt','Pé','Szo','Vas') :
array('','Mon','Tue','Wed','Thu','Fri','Sat','Sun');
$buffer = array();
$last_timestamp = $result[0]['timestamp'];
$burst_start_timestamp = $result[0]['timestamp'];
// Képek batch-ekbe rendezése
foreach($result as $sor) {
if (! empty($buffer) AND $sor['timestamp']-$previous_timestamp > $groupping_time) {
$m = $month[(int)strftime('%m',$previous_timestamp/1000)];
$w = $day[(int)strftime('%w',$previous_timestamp/1000)];
$t1 = trim(strftime('%k:%M:%S',$burst_start_timestamp/1000));
$t2 = trim(strftime('%k:%M:%S',$previous_timestamp/1000));
$t = ($t1 === $t2 ? $t1 : $t1." - ".$t2);
$group_key = strftime("%Y. $m. %e. ($w) $t", $burst_start_timestamp/1000);
$answer[$group_key] = $buffer;
$buffer = array();
$burst_start_timestamp = $sor['timestamp'];
$last_timestamp = $sor['timestamp'];
class Burst {
var $first_timestamp;
var $last_timestamp;
var $xmin,$ymin,$xmax,$ymax;
var $items = array();
var $grouping_time = 3000;
function __construct($new_item) {
$this->first_timestamp = $new_item['timestamp'];
$this->add($new_item);
}
$previous_timestamp = $sor['timestamp'];
array_push($buffer, array(
'thumbnail_ID' => $sor['thumbnail_ID'],
'photo_path' => substr($sor['path'],$path_part_to_remove_length),
'thumb_path' => substr($sor['thumbnail_path'],$path_part_to_remove_length),
function check($new_item) {
// If less than 10 sec between the new item and the last item in that burst
// and center of the new frame is inside the previous frame
return ($new_item['timestamp'] - $this->last_timestamp < $this->grouping_time
AND $this->xmin < $new_item['xcenter'] AND $this->ymin < $new_item['ycenter']
AND $new_item['xcenter'] < $this->xmax AND $new_item['ycenter'] < $this->ymax);
}
function add($new_item) {
$this->last_timestamp = $new_item['timestamp'];
array_push($this->items, array(
'thumbnail_ID' => $new_item['thumbnail_ID'],
'photo_path' => $new_item['photo_path'],
'thumbnail_path' => $new_item['thumbnail_path'],
));
$this->xmin = $new_item['xmin'];
$this->ymin = $new_item['ymin'];
$this->xmax = $new_item['xmax'];
$this->ymax = $new_item['ymax'];
}
// Ha kevesebb, mint 1000 kép van, akkor mindenképp menjen ki az összes
if (count($result) < $limit AND ! empty($buffer)) {
$m = $month[(int)strftime('%m',$previous_timestamp/1000)];
$w = $day[(int)strftime('%w',$previous_timestamp/1000)];
$t1 = strftime('%k:%M:%S',$burst_start_timestamp/1000);
$t2 = strftime('%k:%M:%S',$previous_timestamp/1000);
function toArray() {
global $month;
global $day;
$m = $month[(int)strftime('%m',$this->last_timestamp/1000)];
$w = $day[(int)strftime('%w',$this->last_timestamp/1000)];
$t1 = trim(strftime('%k:%M:%S',$this->first_timestamp/1000));
$t2 = trim(strftime('%k:%M:%S',$this->last_timestamp/1000));
$t = ($t1 === $t2 ? $t1 : $t1." - ".$t2);
$group_key = strftime("%Y. $m. %e. ($w) $t", $burst_start_timestamp/1000);
$answer[$group_key] = $buffer;
$burst_start_timestamp = $sor['timestamp'];
$last_timestamp = $sor['timestamp'];
$title = strftime("%Y. $m. %e. ($w) $t", $this->first_timestamp/1000);
return array($title => $this->items);
}
}
class BurstManager {
var $burst_array = array();
var $last_timestamp;
var $path_part_to_remove = '/home/csbotos/video/';
var $path_part_to_remove_length;
function __construct() {
$this->path_part_to_remove_length = strlen($this->path_part_to_remove);
}
// Adatok elküldése
function add($new_value) {
$this->last_timestamp = $new_value['timestamp'];
$new_value['photo_path'] = substr($new_value['photo_path'],$this->path_part_to_remove_length);
$new_value['thumbnail_path'] = substr($new_value['thumbnail_path'],$this->path_part_to_remove_length);
$new_value['xcenter'] = ($new_value['xmin'] + $new_value['xmax']) / 2;
$new_value['ycenter'] = ($new_value['ymin'] + $new_value['ymax']) / 2;
foreach($this->burst_array as &$burst)
if ($burst->check($new_value)){
$burst->add($new_value);
return; }
array_push($this->burst_array, new Burst($new_value));
}
function toArray($all) {
$array_length = count($this->burst_array);
$return_value = array();
foreach($this->burst_array as $item)
$return_value += $item->toArray();
return $return_value;
}
}
// Order images to bursts according to their timestamp and frame locations
$burstManager = new BurstManager();
foreach($result as $row)
$burstManager->add($row);
// Sending data
die(json_encode(array(
'photos' => $answer,
'last_timestamp' => $last_timestamp,
'photos' => $burstManager->toArray(count($result) < $limit),
'last_timestamp' => $burstManager->last_timestamp,
'result' => $result,
)));
// Tömörítő elengedi a bufferelt adatokat
ob_end_flush();
......@@ -9,7 +9,9 @@
<title>Sam</title>
<link rel="shortcut icon" href="../logo.ico">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4"
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"
integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4"
crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Quicksand:400,500" rel="stylesheet">
......@@ -124,6 +126,8 @@
color: white !important;
opacity: 0.7;
cursor: pointer;
display: inline-block;
margin-bottom: .2em;
}
.group-select:hover {
......@@ -301,6 +305,20 @@
</div>
</div>
</div>
<div id="no-photo" style="display:none">
<div class="row">
<div class="col-sm-10 offset-sm-1 col-lg-8 offset-lg-2">
<p>
<span class="text">
By now there is no photo that is uncertain for us whether or not showing you.
Maybe there will be some soon, so visit again a few days later.</span>
<span class="text" style="display:none">
Jelenleg nincs olyan kép, aminek a tekintetében bizonytalanok lennénk, hogy te vagy-e rajta.
Talán hamarosan lesznek ilyen képek, szóval látogass vissza pár nap múlva!</span>
</p>
</div>
</div>
</div>
<div id="image-wrapper">
</div>
</div>
......@@ -320,7 +338,8 @@
else setTimeout(() => waitFor(what, callback), 50);
}
function receivePhotos(data) {
var parsed = JSON.parse(data);
answer = data;
parsed = JSON.parse(data);
var photos = parsed['photos'];
last_timestamp = parsed['last_timestamp']; // global variable!
var html = "";
......@@ -338,7 +357,7 @@
<span class="lightbox" href="../img/${photo['photo_path']}">
<input type="checkbox" id="${photo['thumbnail_ID']}" data-group="${date}" />
<label for="${photo['thumbnail_ID']}" class="img-outer">
<img class="img-inner" data-src="../img/${photo['thumb_path']}&80" />
<img class="img-inner" data-src="../img/${photo['thumbnail_path']}&80" />
</label>
</span>
</div>`;
......@@ -353,6 +372,7 @@
.prop("indeterminate", $(this).hasClass("idn"))
.prop("checked", $(this).hasClass("ok"));
});
return Object.keys(photos).length > 0;
}
function setupLightbox() {
new LuminousGallery(
......@@ -366,8 +386,8 @@
var postData = typeof shibboleth !== 'undefined' ? {'uid':shibboleth} : {};
$.post("data.php", postData)
.done(data => {
receivePhotos(data);
$("#description").show();
var isAnyPhotos = receivePhotos(data);
$(isAnyPhotos ? "#description" : "#no-photo").show();
waitFor("LazyLoad", () => myLazyLoad = new LazyLoad());
waitFor("Luminous", setupLightbox);
})
......@@ -375,6 +395,7 @@
.always(() => $("#loader").hide());
}
function save() {
$("#loader").show();
IDs = {};
IDs.accepted = [];
IDs.rejected = [];
......@@ -390,15 +411,19 @@
IDs.uid = shibboleth;
$.post("data.php", IDs)
.done(data => {
gdata = data; // TODO only for debug
receivePhotos(data);
var isAnyPhotos = receivePhotos(data);
if (! isAnyPhotos) {
$("#description").hide();
$("#no-photo").show();
}
for (var ID of IDs.accepted.concat(IDs.rejected))
$('div #'+ID).closest('div').remove()
for (var item of $('.img-burst'))
if (item.children.length == 0) $(item).parent().remove();
myLazyLoad.update();
setupLightbox();
});
})
.always(() => $("#loader").hide());
}
</script>
......
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>Az oldal felújítás alatt, kérlek, látogass vissza később (pár óra múlva).</p>
</body>
</html>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment