diff --git a/check.pl b/check.pl index 4c87106b..147e5ca0 100755 --- a/check.pl +++ b/check.pl @@ -88,23 +88,26 @@ for my $f (readdir $dh) # Register solve if ($good == -1) { - say localtime().": Exercice $exercice doesn't exist ; given by team $team in theme $theme."; + say STDERR localtime().": Exercice $exercice doesn't exist ; given by team $team in theme $theme."; } elsif ($good == 1) { # Check if the exercice exists $sth = query($dbh, "SELECT `require` FROM exercices E WHERE E.id_theme = $theme AND E.id = ".$dbh->quote($exercice)); - if ($sth->rows && (my $row = get_row($sth))) + if ($sth->rows) { + my $row = get_row($sth); + # Check if the team has solved dependancies - $sth = query($dbh, "SELECT COUNT(S.id) FROM solved S WHERE S.id_exercice = ".$dbh->quote(@$row[0])) if @$row[0]; - if (! (@$row[0] && $sth->rows)) + $sth = query($dbh, "SELECT S.id FROM solved S WHERE S.id_exercice = ".$dbh->quote(@$row[0])) if @$row[0]; + if (! @$row[0] || $sth->rows) { # Check if the team has not already solved this exercice - $sth = query($dbh, "SELECT COUNT(S.id) FROM solved S WHERE S.id_exercice = ".$dbh->quote($exercice)); + $sth = query($dbh, "SELECT S.id FROM solved S WHERE S.id_exercice = ".$dbh->quote($exercice)); if (! $sth->rows) { - say localtime().": Team $team solve exercice $exercice in $theme"; + say $team; + say STDERR localtime().": Team $team solve exercice $exercice in $theme"; query($dbh, "INSERT INTO solved (id_team, id_exercice, time) VALUES ($team, ".$dbh->quote($exercice).", CURRENT_TIMESTAMP);"); $exit++; } @@ -121,7 +124,7 @@ for my $f (readdir $dh) } } else { - say localtime().": Team $team didn't give the correct answer for exercice $exercice."; + say STDERR localtime().": Team $team didn't give the correct answer for exercice $exercice."; } # Remove the file diff --git a/clear_cache.sh b/clear_cache.sh new file mode 100755 index 00000000..cb528dd4 --- /dev/null +++ b/clear_cache.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +cd `dirname "$0"` + +for n in "$@" +do + MD5=`echo -n $n | md5sum | cut -d " " -f 1` + if [ -f "onyx/cache/$MD5.cache.php" ] + then + rm -f "onyx/cache/$MD5.cache.php" + echo "--- $n deleted" + else + echo "/!\\ $n not found ($MD5)" + fi +done diff --git a/gen_site.sh b/gen_site.sh index 974eeb67..4667aea2 100755 --- a/gen_site.sh +++ b/gen_site.sh @@ -4,7 +4,7 @@ BASEURL="localhost" SALT_TEAM="connected" OUT_TEAM="./teams" -MAX_PARAL=9 +MAX_PARAL=10 DEBUG=0 @@ -34,8 +34,13 @@ then WGET_OPT="-q" fi +./clear_cache.sh top + mkdir -p out -cd out + +ORIG_DIR=`pwd` +MYTMPDIR=`mktemp -d` +cd "$MYTMPDIR" # First, remove existing version if any rm -rf "$BASEURL" "$OUT_TEAM" @@ -43,15 +48,38 @@ rm -rf "$BASEURL" "$OUT_TEAM" wget $WGET_OPT -m -b "http://$BASEURL/" -o /dev/null mkdir -p "$BASEURL" -ln -sf "`pwd`/../files/" "$BASEURL/files" +ln -sf "$ORIG_DIR/files/" "$BASEURL/files" + +# Get list of teams +TEAMS= +if [ $# -gt 0 ] +then + while [ $# -gt 0 ] + do + TEAMS="$TEAMS /$SALT_TEAM/$1/" + shift + done + FULLSYNC=0 +else + for l in $(curl -k "http://$BASEURL/$SALT_TEAM/" 2> /dev/null | grep -oE "/[^/]+/[0-9]+/") + do + TEAMS="$TEAMS $l" + done + FULLSYNC=1 +fi + +echo "Team list to generate: $TEAMS" NB=0 PIDLIST= -# Get list of teams and fetch them in parallel -for l in $(curl -k "http://$BASEURL/$SALT_TEAM/" 2> /dev/null | grep -oE "/[^/]+/[0-9]+/") +# Fetch them in parallel +for l in $TEAMS do ( - wget $WGET_OPT -m "http://$BASEURL/$l" + if ! wget $WGET_OPT -m "http://$BASEURL/$l" + then + exit 1 + fi for m in $(grep -R "
&2 + exit $ERR + +else + MOREOPT= + if [ "$FULL" -eq "1" ] + then + MOREOPT="--delete" + fi + # Ok, now, sync files with prod + rsync -av $MOREOPT * "$ORIG_DIR/out" + + cd "$ORIG_DIR" + rm -rf "$MYTMPDIR" +fi diff --git a/launch.sh b/launch.sh new file mode 100755 index 00000000..5847e65c --- /dev/null +++ b/launch.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +cd `dirname "$0"` + +if [ "$UID" = "0" ] +then + SCRIPT=`pwd`/`basename "$0"` + su -c "sh $SCRIPT" synchro + exit $? +fi + +touch ./logs/checks.log +tail -f ./logs/checks.log & + +FULLREGEN=0 + +while true; +do + if [ "$FULLREGEN" != "0" ] + then + ./synchro.sh + else + ./synchro.sh delete + fi + + if [ `ls submission | wc -l` -gt 1 ] + then + TMPF=`mktemp` + if ! ./check.pl 2>> ./logs/checks.log > "$TMPF" + then + FULLREGEN=1 + fi + + if [ `cat "$TMPF" | wc -l` -gt 0 ] + then + while ! cat "$TMPF" | xargs ./gen_site.sh + do + echo "FAIL regeneration, retry..." 1>&2 + done + fi + rm "$TMPF" + + elif [ "$FULLREGEN" != "0" ] + then + while ! ./gen_site.sh; do + echo "FAIL regeneration, retry..." 1>&2 + done + FULLREGEN=0 + + else + sleep 1 + fi +done diff --git a/nginx.conf b/nginx.conf index 1ed8be7d..04144ca7 100644 --- a/nginx.conf +++ b/nginx.conf @@ -21,6 +21,7 @@ server { location / { default_type text/html; + expires epoch; set $team 0; diff --git a/onyx/include/admin/list_themes.php b/onyx/include/admin/list_themes.php index 5b74f0b9..a52a60f1 100644 --- a/onyx/include/admin/list_themes.php +++ b/onyx/include/admin/list_themes.php @@ -18,6 +18,8 @@ function remove_themes($id) $db->query("DELETE FROM exercices WHERE id_theme = ".$id); $db->query("DELETE FROM themes WHERE id = ".$id); $db->deconnexion(); + + Cache::del("ordered_th".$id); } if (!empty($_GET["delete"])) diff --git a/onyx/include/common/Exercice.class.php b/onyx/include/common/Exercice.class.php index df3cde50..d74111f9 100644 --- a/onyx/include/common/Exercice.class.php +++ b/onyx/include/common/Exercice.class.php @@ -75,6 +75,23 @@ class Exercice } } + static function __set_state(array $array) + { + $tmp = new Exercice(); + + $tmp->id = $array["id"]; + $tmp->number = $array["number"]; + $tmp->theme = $array["theme"]; + $tmp->require = $array["require"]; + $tmp->level = $array["level"]; + $tmp->points = $array["points"]; + $tmp->statement = $array["statement"]; + $tmp->files = $array["files"]; + $tmp->keys = $array["keys"]; + + return $tmp; + } + function get_id() { return $this->id; @@ -89,10 +106,12 @@ class Exercice // trié par date function get_solved() { - $db = new BDD(); + $id = $this->id; + $db = new BDD(); + $db->escape($id); $res = $db->query("SELECT `id_team`, `time` FROM solved - WHERE id_exercice = '$this->id' + WHERE id_exercice = '$id' ORDER BY time"); $db->deconnexion(); @@ -105,11 +124,13 @@ class Exercice if ($this->require == "") return 1; - $db = new BDD(); + $req = $this->require; + $db = new BDD(); + $db->escape($req); $res = $db->unique_query("SELECT `id` FROM solved WHERE id_team = '".intval($team->id)."' - AND id_exercice = '$this->require'"); + AND id_exercice = '$req'"); $db->deconnexion(); if (empty($res)) return 0; @@ -118,9 +139,11 @@ class Exercice function has_solved($team) { - $db = new BDD(); + $id = $this->id; - $res = $db->unique_query("SELECT `time` FROM solved WHERE id_exercice = '$this->id' + $db = new BDD(); + $db->escape($id); + $res = $db->unique_query("SELECT `time` FROM solved WHERE id_exercice = '$id' AND id_team = ".intval($team->get_id())); $db->deconnexion(); @@ -143,6 +166,7 @@ class Exercice do { array_push($checked, $exo); + $db->escape($exo); $res = $db->unique_query("SELECT `require` FROM exercices WHERE id = '".$exo."'"); $exo = $res['require']; $ret++; @@ -278,6 +302,28 @@ class Exercice return $res['max']; } + + public function first_to_solve_exercice() + { + $db = new BDD(); + + $id = $this->id; + $db->escape($id); + + $res = $db->unique_query("SELECT t3.team_name as result + FROM solved AS t1 + INNER JOIN ( + SELECT MIN(s.time) AS minTime + FROM solved AS s + WHERE s.id_exercice = '".$id."' + ) AS t2 + INNER JOIN teams AS t3 ON t1.id_team = t3.id + WHERE t1.time = t2.minTime"); + $db->deconnexion(); + + return $res['result']; + } + } class ExerciceNotFoundException extends Exception diff --git a/onyx/include/common/Team.class.php b/onyx/include/common/Team.class.php index 35a48d45..88b4c8ec 100644 --- a/onyx/include/common/Team.class.php +++ b/onyx/include/common/Team.class.php @@ -60,6 +60,22 @@ class Team } } + static function __set_state(array $array) + { + $tmp = new Team(); + + $tmp->id = $array["id"]; + $tmp->team_name = $array["team_name"]; + $tmp->key_hash = $array["key_hash"]; + $tmp->auth_level = $array["auth_level"]; + $tmp->slogan = $array["slogan"]; + $tmp->members = $array["members"]; + $tmp->points = $array["points"]; + $tmp->revoked = $array["revoked"]; + + return $tmp; + } + // Class methods function update() { @@ -274,14 +290,20 @@ class Team public static function get_top($nb=0) { - $teams = Team::get_teams(); + $top = Cache::read("top"); + if (empty($top)) + { + $top = Team::get_teams(); - usort($teams, "cmp_team_pts"); + usort($top, "cmp_team_pts"); + + Cache::set("top", $top); + } if ($nb != 0) - $teams = array_slice($teams, 0, $nb); + $top = array_slice($top, 0, $nb); - return $teams; + return $top; } public static function get_nb_teams() @@ -292,21 +314,4 @@ class Team return $res['count_teams']; } - - public static function first_to_solve_exercice($id_exercice) - { - $db = new BDD(); - $res = $db->unique_query("SELECT t3.team_name as result - FROM solved AS t1 - INNER JOIN ( - SELECT MIN(s.time) AS minTime - FROM solved AS s - WHERE s.id_exercice = ".$id_exercice." - ) AS t2 - INNER JOIN teams AS t3 ON t1.id_team = t3.id - WHERE t1.time = t2.minTime"); - $db->deconnexion(); - - return $res['result']; - } } diff --git a/onyx/include/common/Theme.class.php b/onyx/include/common/Theme.class.php index 9ff832c4..c155fcb7 100644 --- a/onyx/include/common/Theme.class.php +++ b/onyx/include/common/Theme.class.php @@ -29,6 +29,16 @@ class Theme } } + static function __set_state(array $array) + { + $tmp = new Theme(); + + $tmp->id = $array["id"]; + $tmp->name = $array["name"]; + + return $tmp; + } + function update() { $name = $this->name; @@ -52,6 +62,8 @@ class Theme } $db->deconnexion(); + Cache::del("ordered_th".$this->id); + return ($aff == 1); } @@ -93,6 +105,10 @@ class Theme function get_exercices_ordered() { + $res = Cache::read("ordered_th".$this->id); + if (!empty($res)) + return $res; + $db = new BDD(); $res = $db->query("SELECT E.id, E.require FROM exercices E INNER JOIN themes T ON T.id = E.id_theme @@ -130,13 +146,14 @@ class Theme foreach($res as &$r) $r = new Exercice($r["id"]); + Cache::set("ordered_th".$this->id, $res); return $res; } public static function get_themes() { $db = new BDD(); - $ids = $db->query("SELECT `id` FROM `themes`"); + $ids = $db->query("SELECT `id` FROM `themes` ORDER BY `name`"); $db->deconnexion(); $array = array(); diff --git a/onyx/require/cache.php b/onyx/require/cache.php index 70564154..0971f736 100644 --- a/onyx/require/cache.php +++ b/onyx/require/cache.php @@ -2,34 +2,45 @@ class Cache { - + static function set($id,$var) { $file = ''; - - file_put_contents(ONYX.'cache/'.md5($id).'.cache.php',$file) or trigger_error('dossier cache inaccessible en écriture.',E_USER_ERROR); + + $tmpfname = tempnam("/tmp", "cache"); + + if(file_put_contents($tmpfname, $file, LOCK_EX) !== FALSE) + rename($tmpfname, ONYX.'cache/'.md5($id).'.cache.php') or trigger_error('dossier cache inaccessible en écriture.',E_USER_ERROR); + else + trigger_error('impossible d\'?crire dans '.$tmpfname,E_USER_ERROR); } - + static function read($id) { if(!is_readable(ONYX.'cache/'.md5($id).'.cache.php')) return FALSE; - - include(ONYX.'cache/'.md5($id).'.cache.php'); - if(!$cache) return FALSE; + + $tmpfname = tempnam("/tmp", "cache"); + copy(ONYX.'cache/'.md5($id).'.cache.php', $tmpfname); + + include($tmpfname); + + unlink($tmpfname); + + if(empty($cache)) return FALSE; return $cache; } - + static function del($id) { if(!is_file(ONYX.'cache/'.md5($id).'.cache.php')) return FALSE; return unlink(ONYX.'cache/'.md5($id).'.cache.php'); } - + static function flush() { foreach(glob(ONYX.'cache/*.cache.php') as $file) unlink($file); } - + } ?> \ No newline at end of file diff --git a/onyx/tpl/bootstrap/public/home.tpl b/onyx/tpl/bootstrap/public/home.tpl index 73af278d..e97c2cef 100644 --- a/onyx/tpl/bootstrap/public/home.tpl +++ b/onyx/tpl/bootstrap/public/home.tpl @@ -1,9 +1,13 @@ {extends file="public/layout.tpl"} {block name=main} -
- - + {if isset($teams)} +
@@ -21,7 +25,7 @@ {foreach from=$theme->get_exercices_ordered() item=exo} {$teamName=""} {for $i=0 to $nbExoMax} - {$teamName=Team::first_to_solve_exercice($exo->get_id())} + {$teamName=$exo->first_to_solve_exercice()} {/for} {if $teamName != ""} @@ -33,6 +37,20 @@ {/foreach}
{$teamName}
+
+ + {foreach from=$teams item=my_team key=k} +
+
+ {include file="summary.tpl"} +
+ {/foreach} + + +{/if} + + + {/block} diff --git a/onyx/tpl/bootstrap/public/layout.tpl b/onyx/tpl/bootstrap/public/layout.tpl index a71a787b..da0bfa40 100644 --- a/onyx/tpl/bootstrap/public/layout.tpl +++ b/onyx/tpl/bootstrap/public/layout.tpl @@ -17,32 +17,23 @@ {/if}
-
+

Top 10

{foreach from=$top item=t key=k} -
{$k+1}. {link href="{$t->id}-{$t->get_name()}" href_prefix="/" label=$t->get_name()}
+
{$k+1}. {link href="{$t->id}-{$t->get_name()}" href_prefix="/" label=$t->get_name()} + +{$t->get_pts()} + +
{/foreach}
-
+
{block name=main}{/block}
-{if isset($teams)} - -{/if}
{/block} @@ -54,7 +45,7 @@ $(document).ready(function() { update_end(); $('#carousel-team').carousel({ - interval: 5000 }); + interval: 10000 }); setInterval( function() { update_end(); diff --git a/onyx/tpl/bootstrap/public/score.tpl b/onyx/tpl/bootstrap/public/score.tpl index 5b113b44..1bfec7c4 100644 --- a/onyx/tpl/bootstrap/public/score.tpl +++ b/onyx/tpl/bootstrap/public/score.tpl @@ -2,7 +2,6 @@ {block name=main}
-

{$my_team->get_name()}

{include file="summary.tpl"}
{/block} diff --git a/onyx/tpl/bootstrap/summary.tpl b/onyx/tpl/bootstrap/summary.tpl index e65c6d12..1eed15df 100644 --- a/onyx/tpl/bootstrap/summary.tpl +++ b/onyx/tpl/bootstrap/summary.tpl @@ -1,7 +1,7 @@ - +
- + {for $i=1 to $nbExoMax} {/for} @@ -12,7 +12,7 @@ {$total=0} {foreach from=$themes item=theme} - + {$sum=0} {$cpt=0} {$themeID=$theme->get_id()} @@ -43,8 +43,8 @@ - - + +
{$my_team->get_name()}{$my_team->get_name()}Exercice {$i}
{$theme->get_name()}{$theme->get_name()}
Total :{$total}Total :{$total}
diff --git a/onyx/tpl/bootstrap/teams/exercice.tpl b/onyx/tpl/bootstrap/teams/exercice.tpl index d07770c8..a487174c 100644 --- a/onyx/tpl/bootstrap/teams/exercice.tpl +++ b/onyx/tpl/bootstrap/teams/exercice.tpl @@ -8,7 +8,7 @@
  • Gain : {$cur_exercice->points}
  • -
  • Description : {$cur_exercice->statement}
  • +
  • Description : {$cur_exercice->statement|escape|nl2br}
diff --git a/synchro.sh b/synchro.sh index 4ffc1ef3..9ea8a4b9 100755 --- a/synchro.sh +++ b/synchro.sh @@ -5,17 +5,23 @@ cd `dirname "$0"` if [ "$UID" = "0" ] then SCRIPT=`pwd`/`basename "$0"` - su -c "sh $SCRIPT" synchro + su -c "sh $SCRIPT $@" synchro exit $? fi -rsync -e ssh -av --delete out/localhost/* phobos:~/htdocs/ -rsync -e ssh -av --delete out/teams phobos:~/ -rsync -e ssh -av --delete files phobos:~/ -rsync -e ssh -av --delete misc phobos:~/ +OPTS= +if [ "$1" = "delete" ] +then + OPTS="$OPTS --delete" +fi + +rsync -e ssh -av $OPTS out/localhost/* phobos:~/htdocs/ +rsync -e ssh -av $OPTS out/teams phobos:~/ +rsync -e ssh -av $OPTS files phobos:~/ +rsync -e ssh -av $OPTS misc phobos:~/ scp nginx.conf submission.php phobos:~/ -rsync -e ssh -av --delete out/localhost/* phobos:~/htdocs/ +rsync -e ssh -av $OPTS out/localhost/* phobos:~/htdocs/ rsync -e ssh -av phobos:~/submission/ submission/ ssh phobos "rm ~/submission/*"