Skip to content

Instantly share code, notes, and snippets.

@pallada-92
Last active April 3, 2019 19:18
Show Gist options
  • Save pallada-92/890e41d7598163d4fc6828519dff7445 to your computer and use it in GitHub Desktop.
Save pallada-92/890e41d7598163d4fc6828519dff7445 to your computer and use it in GitHub Desktop.
Killer Web App (Google App Engine)
абсолютный
аккуратный
активный
американский
английский
армейский
атомный
багровый
бедный
безнадежный
безумный
белый
бесконечный
бесплатный
беспомощный
бессмертный
бессмысленный
бетонный
бешеный
биологический
благодарный
благородный
бледный
блестящий
ближайший
близкий
богатый
боевой
божий
боковой
болезненный
больной
больший
большой
босой
брезгливый
британский
будущий
бумажный
бурный
бурый
бывший
быстрый
важный
ванный
великий
великолепный
верный
верхний
верховный
веселый
весенний
вечерний
вечный
вещий
взрослый
видимый
видный
виноватый
вкусный
влажный
влюбленный
внезапный
внешний
внимательный
внутренний
военно
военный
воздушный
возможный
волшебный
вольный
вонючий
вооруженный
восточный
вредный
временный
всеобщий
встречный
вчерашний
выдающийся
вынужденный
выраженный
высокий
высший
выходной
газетный
генеральный
гениальный
германский
гигантский
главный
гладкий
глубокий
глупый
глухой
головной
голодный
голубой
голый
гордый
горный
городской
горький
горячий
гостиный
государственный
готовый
гражданский
грозный
громадный
громкий
грубый
грустный
грязный
густой
давний
далекий
дальнейший
дальний
данный
двойной
дежурный
действующий
деловитый
деловой
демократический
денежный
деревенский
деревянный
детский
дешевый
дикий
длинный
длительный
дневной
добрый
довольный
долгий
должный
домашний
дополнительный
допустимый
дорогой
достаточный
достойный
доступный
дошлый
драгоценный
древний
дурацкий
дурной
духовный
душевный
еврейский
европейский
единственный
единый
естественный
жалкий
жаркий
железнодорожный
железный
желтый
женатый
женский
жесткий
жестокий
живой
животный
жидкий
жизненный
жирный
жуткий
забытый
загадочный
задний
законный
закрытый
заметный
замечательный
занятый
западный
зарубежный
звездный
звонкий
здешний
здоровенный
здоровый
зеленый
земной
зимний
зловещий
знакомый
знаменитый
значительный
знающий
золотой
идеальный
идеологический
известный
излишний
изящный
индивидуальный
иностранный
интеллектуальный
интеллигентный
интересный
информационный
искусственный
испуганный
истинный
исторический
итальянский
казенный
каменный
квадратный
китайский
классический
книжный
кожаный
колючий
командующий
коммерческий
коммунистический
комсомольский
конечный
конкретный
корейский
коричневый
королевский
короткий
космический
косой
крайний
красивый
красный
крепкий
крестьянский
кривой
кровавый
крохотный
крошечный
круглый
крупнейший
крупный
крутой
культурный
лагерный
ласковый
левый
легкий
ледяной
лекарственный
ленинградский
ленинский
лесной
летний
лиловый
литературный
личный
лишенный
лишний
ложный
лунный
лучший
лысый
любимый
любопытный
людской
магический
максимальный
малейший
маленький
малый
массовый
материальный
матерый
машинальный
медицинский
медленный
медный
международный
мелкий
меньший
мертвый
местный
металлический
механический
милый
мирный
мировой
младший
многочисленный
могучий
модный
мокрый
молоденький
молодой
молочный
молчаливый
моральный
мороженый
морской
московский
мостовый
мощный
мрачный
мудрый
мужской
музыкальный
мутный
мучительный
мягкий
набитый
надежный
наивный
налоговый
напряженный
народный
настоящий
научный
национальный
небесный
небольшой
неведомый
невероятный
невидимый
невозможный
невыносимый
невысокий
недавний
недовольный
нежный
независимый
незнакомый
незначительный
неизбежный
неизвестный
нелепый
немалый
немецкий
немой
ненужный
необходимый
необыкновенный
необычный
неожиданный
неопределенный
неплохой
неподвижный
непонятный
непосредственный
неправильный
непривычный
неприятный
нервный
несчастный
нетерпеливый
неторопливый
неуверенный
нехороший
неясный
нижний
низкий
нищий
новенький
новый
нормальный
ночной
нравственный
нужный
нынешний
образованный
обратный
обреченный
обширный
общественный
общий
объективный
обыкновенный
обычный
обязанный
обязательный
огненный
ограниченный
огромный
одетый
одинаковый
одинокий
окончательный
окружающий
опасный
оперативный
определенный
опытный
оранжевый
оригинальный
осенний
основной
особенный
особый
осторожный
острый
ответственный
отвратительный
отдаленный
отдельный
отечественный
открытый
отличный
отрицательный
отчаянный
офицерский
официальный
очевидный
очередной
парадный
партийный
передний
передовой
пестрый
печальный
письменный
пленный
плоский
плотный
плохой
повышенный
подводной
подземный
подлинный
подобный
подозрительный
подробный
подходящий
подчиненный
пожарный
пожилой
поздний
полевой
полезный
политический
полицейский
полный
половый
положенный
положительный
польский
понятный
популярный
порядочный
последний
последующий
посторонний
постоялый
постоянный
похожий
почетный
почтительный
пошлый
правильный
правительственный
правый
праздничный
практический
предстоящий
предыдущий
прежний
презрительный
прекрасный
преступный
привычный
приезжий
приемный
приличный
принятый
природный
присутствующий
пришлый
приятный
прозрачный
производственный
проклятый
промышленный
простой
просторный
противный
противоположный
профессиональный
прохладный
прохожий
прочный
прошедший
прошлый
прямой
психический
психологический
пустой
пустынный
пыльный
пышный
пьяный
рабочий
равнодушный
равный
радостный
разбитый
развитый
различный
разнообразный
разноцветный
разный
разумный
районный
раненый
ранний
раскрытый
реальный
революционный
редкий
резиновый
резкий
религиозный
решительный
ржавый
римский
ровный
родной
розовый
роскошный
рослый
российский
русский
ручной
рыжий
рядовой
самостоятельный
свежий
сверкающий
светлый
свободный
своеобразный
свойственный
связанный
святой
священный
северный
сегодняшний
седой
секретный
сексуальный
сельский
семейный
сердечный
серебряный
серый
серьезный
сильный
симпатичный
синий
склонный
скорый
скромный
скрытый
скучный
слабый
славный
сладкий
следующий
слепой
слизистый
сложенный
сложный
служебный
случайный
слышный
смелый
смертельный
смертный
смешной
смуглый
смутный
снежный
снисходительный
собачий
собственный
совершенный
советский
совместный
современный
согласный
солдатский
солидный
солнечный
сомнительный
сонный
соответствующий
соседний
социалистический
социальный
специальный
сплошной
спокойный
спортивный
способный
справедливый
средний
сталинский
стальной
старательный
старенький
старинный
старший
старый
стеклянный
столичный
столовый
стоящий
странный
стратегический
страшный
строгий
стройный
студенческий
стыдный
судебный
сумасшедший
суровый
сухой
существенный
существующий
счастливый
сырой
сытый
таинственный
тайный
талантливый
твердый
творческий
театральный
телефонный
темный
теплый
тесный
технический
типичный
тихий
толстый
тоненький
тонкий
торговый
торжественный
торопливый
точный
тощий
трагический
традиционный
тревожный
трезвый
трудный
трудовой
тупой
тусклый
тюремный
тяжелый
тяжкий
убежденный
убитый
уважаемый
уверенный
угодный
уголовный
угрюмый
удачный
удивительный
удобный
ужасный
узкий
указанный
украинский
уличный
умный
уникальный
усталый
утренний
учебный
ученый
уютный
фальшивый
фантастический
физический
финансовый
французский
характерный
химический
хитрый
хозяйственный
холодный
хорошенький
хороший
хронический
художественный
худой
царский
цветной
целый
ценный
центральный
часовой
частный
частый
человеческий
черный
чертовый
честной
четкий
чеченский
чистый
чудесный
чудовищный
чужой
шампанский
шелковый
широкий
школьный
шумный
экономический
электрический
электронный
эмоциональный
энергичный
эффективный
южный
явный
японский
яркий
ясный
<!DOCTYPE html>
{% autoescape true %}
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="static/target.png" />
<title>{{user.first_name}} {{user.last_name}} &mdash; Редактирование &mdash; Игра &laquo;Киллер&raquo;</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<center>
<br>
<a href="/admin">Центр управления</a>
<h1>{{user.first_name}} {{user.last_name}}</h1>
<br><br>
<div class="row">
<div class="col-sm-4">
<div class="row">
<p class="text-center"><a href="http://vk.com/id{{user.uid}}">Страница vk.com</a></p>
</div>
<div class="row">
<p class="text-center"><a href="/admin?action=login_as_other_user&amp;user_id={{user.uid}}" class="btn btn-xs btn-default">Зайти в систему как этот пользователь</a></p>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Id: </p></div>
<div class="col-sm-6"><p class="text-left">{{user.uid}}</p></div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Пол: </p></div>
<div class="col-sm-6"><p class="text-left">
{% if user.sex == '1' %}
Женский
{% else %}
Мужской
{% endif %}
</p></div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Участвует в игре:</p></div>
<div class="col-sm-6" style="text-align:left">
{% if game_status != 'registration-opened' and game_status != 'registration-closed' %}
{% if user.enabled %}
Да
{% else %}
Нет
{% endif %}
{% else %}
<div class="btn-group btn-group-xs">
<a {% if user.enabled %} href="#" class="btn btn-default btn-sm active"{% else %} href="/admin?action=toggle_enabled&amp;user_id={{user.uid}}" class="btn btn-default btn-sm" {% endif %}>Да</a>
<a {% if not user.enabled %} href="#" class="btn btn-default btn-sm active"{% else %} href="/admin?action=toggle_enabled&amp;user_id={{user.uid}}" class="btn btn-default btn-sm" {% endif %}>Нет</a>
</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Принял соглашение: </p></div>
<div class="col-sm-6"><p class="text-left"> {% if user.license_accepted %} Да {% else %} Нет {% endif %}</p></div>
</div>
{% if user.enabled %}
<div class="row">
<div class="col-sm-6"><p class="text-right"> Живой: </p></div>
<div class="col-sm-6" style="text-align:left">
<div class="btn-group btn-group-xs">
<a {% if user.alive %} href="#" class="btn btn-default btn-sm active"{% else %} href="/admin?action=toggle_alive&amp;user_id={{user.uid}}" class="btn btn-default btn-sm" {% endif %}>Да</a>
<a {% if not user.alive %} href="#" class="btn btn-default btn-sm active"{% else %} href="/admin?action=toggle_alive&amp;user_id={{user.uid}}" class="btn btn-default btn-sm" {% endif %}>Нет</a>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Очков: </p></div>
<div class="col-sm-6" style="text-align:left">
{{user.killed | length}} +
<form action="/admin" method="get" style="display:inline">
<input type="text" size="2" name="additional_points" value="{{additional_points}}">
<input type="hidden" name="action" value="set_additional_points">
<input type="hidden" name="user_id" value="{{user.uid}}">
<input type="submit" value="set">
</form>
</p>
</div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Цель: </p></div>
<div class="col-sm-6"><p class="text-left">
{% for victim_id in user.victims %}
<a href="/admin?action=edit&amp;user_id={{victim_id}}">{{victim_id}}</a><br>
{% endfor %}
<a href="/admin?action=rebuild_kill_graph&amp;return_to=edit&amp;user_id={{user.uid}}" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-refresh"></span> &nbsp; Обновить</a>
</p></div>
</div>
<!--
<div class="row">
<div class="col-sm-6"><p class="text-right"> Имеет карточки: </p></div>
<div class="col-sm-6"><p class="text-left">
{% for card_id in user.has_cards_of %}
<a href="/admin?action=edit&amp;user_id={{card_id}}">{{card_id}}</a>,
{% endfor %}
</p></div>
</div>
-->
{% endif %}
<div class="row">
<div class="col-sm-6"><p class="text-right"> Состоит в группах: </p></div>
<div class="col-sm-6"><p class="text-left">
{% for group in user.groups %}
{{group}},
{% endfor %}
</p></div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Зарегистрирован: </p></div>
<div class="col-sm-6"><p class="text-left">
{{user.date_registered | to_local_time}}
</p></div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Последний раз был на сайте: </p></div>
<div class="col-sm-6"><p class="text-left">
{{user.last_visited | to_local_time}}
</p></div>
</div>
{% if user.enabled %}
<div class="row">
<div class="col-sm-6"><p class="text-right"> Был принят в игру: </p></div>
<div class="col-sm-6"><p class="text-left">
{{user.date_enabled | to_local_time}}
</p></div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Последний раз совершил убийство: </p></div>
<div class="col-sm-6"><p class="text-left">
{{user.last_kill_date | to_local_time}}
</p></div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Прошло дней с последнего убийства: </p></div>
<div class="col-sm-6"><p class="text-left">
{{days_inactive(user)}} ({% if is_inactive(user) %}неактивный{% else %}активный{% endif %})
</p></div>
</div>
{% endif %}
{% if user.enabled and not user.alive %}
<div class="row">
<div class="col-sm-6"><p class="text-right"> Кем убит: </p></div>
<div class="col-sm-6"><p class="text-left">
<a href="/admin?action=edit&amp;user_id={{user.killed_by}}">{{user.killed_by}}</a>
</p></div>
</div>
<div class="row">
<div class="col-sm-6"><p class="text-right"> Когда убит: </p></div>
<div class="col-sm-6"><p class="text-left">
{{user.killed_date | to_local_time}}
</p></div>
</div>
{% endif %}
<div class="row">
<div class="col-sm-6"><p class="text-right"></p></div>
<div class="col-sm-6"><p class="text-left">
<button type="button" id="show-password" class="btn btn-default btn-xs">
Показать пароль
</button>
</p></div>
</div>
</div>
<form action="/admin" method="get">
<input type="hidden" name="action" value="save_user">
<input type="hidden" name="user_id" value="{{user.uid}}">
<div class="col-sm-4">
<label>Большое фото (200px)</label><br>
{% if user.photo %}
<img src="{{user.photo}}" style="max-width:200px"><br><br>
{% else %}
<i><span style="color:gray">Нет большого фото</span></i><br><br>
{% endif %}
<input type="text" class="form-control" placeholder="Ссылка на большое фото" name="photo" value="{% if user.photo %}{{user.photo}}{% endif %}">
<!-- <br><br>
<label>Маленькое фото</label><br>
{% if user.photo_rec %}
<img src="{{user.photo_rec}}" style="max-width:50px"><br><br>
{% elif user.photo %}
<img src="{{user.photo}}" style="max-width:50px"><br><br>
{% else %}
<i><span style="color:gray">Нет маленького фото</span></i><br><br>
{% endif %}
<input type="text" class="form-control" placeholder="Ссылка на маленькое фото" name="photo_rec" value="{% if user.photo_rec %}{{user.photo_rec}}{% endif %}">
(оставьте пустым, чтобы использовать большое фото)<br> -->
</div>
<div class="col-sm-4">
<div class="form-group">
<label>Комментарий<br>(показывается только администраторам)</label>
<input type="text" class="form-control" name="admin_comment" value="{% if user.admin_comment %}{{user.admin_comment}}{% endif %}" placeholder="Комментарий администраторам">
</div>
<div class="form-group">
<label>Информация для этого участника:</label>
<textarea class="form-control" rows="3" name="message" placeholder="Сообщение пользователю">{% if user.message %}{{user.message}}{% endif %}</textarea>
</div>
<button type="submit" class="btn btn-primary">Сохранить</button>
</div>
</form>
</div>
<div style="height:50px"></div>
</center>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script>
var show_pas = true;
$('#show-password').click(function () {
var btn = $(this)
if(show_pas){
btn.text('{{user.password}}');
}else{
btn.text('Показать пароль');
}
btn.button('toggle')
show_pas = !show_pas;
});
</script>
</body>
</html>
{% endautoescape %}
<!DOCTYPE html>
{% autoescape true %}
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="static/target.png" />
<title>Игра &laquo;Киллер&raquo;</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- <script src="static/editor.js"></script> -->
</head>
<body>
<div class="container">
<br>
<!--<div class="alert alert-warning" role="alert">Сайт работает в тестовом режиме. Пожалуйста, не регистрируйтесь до официального запуска.</div>-->
<table width="100%">
<tr><td width="33%" align="left"><a href="/admin?action=news">Новости</a></td>
<td align="center">
</td>
<td width="33%" align="right">
<a href="/?action=logout">Выйти</a> &nbsp; &nbsp;
<a href="/">Войти как обычный пользователь</a>
</td>
</tr>
</table>
<center>
<h1>Центр управления</h1>
<div style="height:45px"></div>
<div class="row">
<div class="col-sm-6">
<h4>Участвуют в игре ({{enabled_users | length}})</h4><br>
{% if sort == 'by_comment' %}
(отсортировано по комментариям)<br>
{% endif %}
<form action="/admin" method="post">
<input type="hidden" name="action" value="set_enabled_users_message">
<div class="form-group">
<label>Сообщение для участников</label>
<textarea type="text" class="form-control" name="enabled_users_message" rows="10">{{enabled_users_message}}</textarea>
</div>
<button type="submit" class="btn btn-default">Сохранить</button><br><br>
</form>
<div class="list-group">
{% for user in enabled_users %}
<a href="/admin?action=edit&amp;user_id={{user.uid}}" class="list-group-item"><table width="100%"><tr><td width="45%" align=right class="list-group-item-heading">
{% if not user.alive %}<strike>{% endif %}
{% if is_inactive(user) %} <span class="label label-default">Н</span> {% endif %}
{{user.first_name}} {{user.last_name}}
{% if not user.alive %}</strike>{% endif %}
</td><td> &nbsp; &nbsp; </td><td width="45%">
{% if user.admin_comment %}
{{user.admin_comment}}
{% endif %}
</td></tr></table></a>
{% endfor %}
</div>
<form action="/admin" method="get">
<input type="hidden" name="action" value="rebuild_kill_graph">
<div class="row">
<div class="col-xs-8">
<input type="text" name="seed" class="form-control" value="{{seed}}">
</div>
<div class="col-xs-4">
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-refresh"></span> &nbsp; Переставить</button>
</div>
</div>
</form>
</div>
<div class="col-sm-6">
<h4>Вне игры ({{disabled_users | length}})</h4><br>
<form action="/admin" method="post">
<input type="hidden" name="action" value="set_disabled_users_message">
<div class="form-group">
<label>Сообщение для этих пользователей</label>
<textarea type="text" class="form-control" name="disabled_users_message" rows="10">{{disabled_users_message}}</textarea>
</div>
<button type="submit" class="btn btn-default">Сохранить</button><br><br>
</form>
<div class="list-group">
{% for user in disabled_users %}
<a href="/admin?action=edit&amp;user_id={{user.uid}}" class="list-group-item"><table width="100%"><tr><td width="45%" align=right class="list-group-item-heading">{{user.first_name}} {{user.last_name}} </td><td> &nbsp; &nbsp; </td><td width="45%">
{% if user.admin_comment %}
{{user.admin_comment}}
{% endif %}
</td></tr></table></a>
{% endfor %}
</div>
</div>
</div>
<div style="height:50px"></div>
Этап игры:<br>
<div class="btn-group">
{% for status in game_statuses %}
{% if status == current_status %}
<a href="#" class="btn btn-default active">{{status}} </a> &nbsp; &nbsp;
{% else %}
<a href="/admin?action=set_game_status&amp;new_status={{ status }}" class="btn btn-default ">{{ status }}</a> &nbsp; &nbsp;
{% endif %}
{% endfor %}
</div>
<div style="height:50px"></div>
<a href="/admin?action=download_dump" class="btn btn-default"><span class="glyphicon glyphicon-cloud-download"></span> &nbsp; Скачать дамп системы</a>
<div style="height:50px"></div>
<!--
<div style="height:50px"></div>
<div id="forcanvas"></div>
<br><br>
<button id="graph_save" class="btn btn-default" onClick="upload_graph()" data-loading-text="Сохраняется..." data-ok-text="Сохранено" data-error-text="Ошибка сохранения">Сохранить</button>-->
<form action="/admin" method="post">
<input type="hidden" name="action" value="set_public_text">
<div class="form-group">
<label>Текст приветствия при авторизации</label>
<textarea class="form-control" name="public_text" rows="15">{{public_text}}</textarea>
</div>
<button type="submit" class="btn btn-default">Сохранить текст приветствия</button>
</form>
<div style="height:50px"></div>
<form action="/admin" method="post">
<input type="hidden" name="action" value="set_rules_text">
<div class="form-group">
<label>Правила игры</label>
<textarea class="form-control" name="rules_text" rows="15">{{rules_text}}</textarea>
</div>
<button type="submit" class="btn btn-default">Сохранить правила</button>
</form>
<div style="height:50px"></div>
</center>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</body>
</html>
{% endautoescape %}
<!DOCTYPE html>
{% autoescape true %}
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="static/target.png" />
<title>Новости для администраторов &mdash; Игра &laquo;Киллер&raquo;</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- <script src="static/editor.js"></script> -->
</head>
<body>
<div class="container">
<br>
<center>
<a href="/admin">Центр управления</a>
<h1>Новости для администраторов</h1>
<div style="height:40px"></div>
{% for news_entry in news_entries %}
<p>{{news_entry.text}}</p>
{% endfor %}
<div style="height:100px"></div>
</center>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</body>
</html>
{% endautoescape %}
application: killer-killer
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /static
static_dir: static
- url: /.*
script: main.application
builtins:
- appstats: on
libraries:
- name: webapp2
version: latest
- name: jinja2
version: latest
def webapp_add_wsgi_middleware(app):
from google.appengine.ext.appstats import recording
app = recording.appstats_wsgi_middleware(app)
return app
<!DOCTYPE html>
{% autoescape true %}
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="static/target.png" />
<title>Игра &laquo;Киллер&raquo;</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- Put this script tag to the <head> of your page -->
<script type="text/javascript" src="//vk.com/js/api/openapi.js?115"></script>
<script type="text/javascript">
VK.init({apiId: 12345678});
</script>
</head>
<body>
<div class="container">
<br>
<!--<div class="alert alert-warning" role="alert">Сайт работает в тестовом режиме. Пожалуйста, не распространяйте ссылку на него до официального запуска.</div>-->
<br><br>
<center>
{% autoescape false %}
{{ public_text }}
{% endautoescape %}
<br>
<div id="vk_auth"></div>
<script type="text/javascript">
VK.Widgets.Auth("vk_auth", {width: "300px", authUrl: '?action=login'});
</script><br><br>
{% if message %}
{% autoescape false %}
<b><span style="color:red">{{ message }}</span></b> <br>
<div style="height: 50px"></div>
{% endautoescape %}
{% endif %}
{% if game_status == 'game-started' %}
<div class="row">
<div class="col-xs-4">
Всего участников:<br>
<h1>{{num_of_enabled_users}}</h1>
</div>
<div class="col-xs-4">
Игра длится дней:<br>
<h1>{{game_lasts_days}}</h1>
</div>
<div class="col-xs-4">
Из них осталось в живых:<br>
<h1>{{num_of_alive_users}}</h1>
</div>
</div>
{% endif %}
{% if game_status == 'registration-opened' %}
Всего зарегистрировалось человек:<br>
<h1>{{ num_of_users }}</h1>
{% endif %}
<div style="height:50px"></div>
<!--- <div id="forcanvas"></div> -->
<br><br>
<!--- <div id="event-mess"> <span id="timetoevent"></span></div> -->
</center>
</div>
<div style="height:40px"></div>
<div style="position:fixed;bottom:0;height:40px;text-valign:top;padding-top:10px;width:100%;text-align:center;background:white; border-top: 1px solid gray">
<!-- Число участников: {{num_of_users}}<br> -->
Администраторы: <a href="http://vk.com/id26769197">Дмитрий Марков</a>, <a href="http://vk.com/id170556210">Бамбр Намжавин</a>, <a href="http://vk.com/id1330405">Элен Теванян</a>. Программирование: <a href="http://vk.com/pallada92">Ярослав Сергиенко</a>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</body>
</html>
{% endautoescape %}
indexes:
# AUTOGENERATED
# This index.yaml is automatically updated whenever the dev_appserver
# detects that a new type of query is run. If you want to manage the
# index.yaml file manually, remove the above marker line (the line
# saying "# AUTOGENERATED"). If you want to manage some indexes
# manually, move them above the marker line. The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.
- kind: User
properties:
- name: enabled
- name: date_enabled
- kind: User
properties:
- name: enabled
- name: date_registered
<!DOCTYPE html>
{% autoescape true %}
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="static/target.png" />
<title>Правила игры &laquo;Киллер&raquo;</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<br>
<center>
{% if not acceptable %}
<a href="/">На главную страницу</a>
{% else %}
{% if accepted %}
<a href="/">На мою страницу</a>
{% else %}
<a href="/?action=logout">Выйти</a>
{% endif %}
{% endif %}
</center>
{% autoescape false %}
{{ rules_text }}
{% endautoescape %}
<center>
{% if acceptable %}
{% if accepted %}
<div class="alert alert-success" role="alert">Вы приняли правила игры.</div>
{% else %}
<a href="/?action=accept_license" class="btn btn-lg btn-primary">Принимаю</a> &nbsp; &nbsp; &nbsp;
<a href="http://google.com">Не принимаю</a>
{% endif %}
{% endif %}
<div style="height:50px"></div>
</center>
</div>
<div style="height:40px"></div>
<div style="position:fixed;bottom:0;height:40px;text-valign:top;padding-top:10px;width:100%;text-align:center;background:white; border-top: 1px solid gray">
<!-- Число участников: {{num_of_users}}<br> -->
Администраторы: <a href="http://vk.com/id26769197">Дмитрий Марков</a>, <a href="http://vk.com/id170556210">Бамбр Намжавин</a>, <a href="http://vk.com/id1330405">Элен Теванян</a>. Программирование: <a href="http://vk.com/pallada92">Ярослав Сергиенко</a>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</body>
</html>
{% endautoescape %}
канал
восток
молодец
человечек
солдатик
выпуск
фокус
рыцарь
побег
город
заговор
порыв
мусор
историк
корень
политик
заведующий
свидетель
покойник
горизонт
артист
перерыв
лидер
красавец
особняк
берлин
автомат
разряд
исход
успех
пиджак
голова
пункт
огород
пушок
кузнец
квартал
сустав
философ
ветерок
локоть
турист
оркестр
советник
защитник
окурок
кислород
ботинок
политика
кулак
третий
представитель
родина
танцор
батальон
цветок
симптом
охранник
шепот
текст
фонтан
ложка
стакан
поезд
пилот
партизан
альбом
гвоздь
снаряд
президент
препарат
хвост
ремонт
охотник
подвал
солдат
интернет
памятник
замок
ответ
идиот
комар
кризис
метода
ветер
доллар
вариант
катер
рамка
запах
рынок
бульвар
набор
доход
процент
предатель
пассажир
виски
кузьмич
центр
писатель
рукав
правитель
фрукт
новичок
париж
чеченец
обитатель
свист
ангел
дровосек
аппетит
отдел
кирпич
носок
госпиталь
замысел
приступ
остаток
метод
сюжет
малый
грохот
роман
хутор
котелок
полок
военный
контроль
ресурс
гараж
парнишка
участок
продукт
красный
факультет
паспорт
рассказ
следователь
стиль
заказ
транспорт
планета
октябрь
секунда
демократ
мороз
диагноз
пастух
образ
металл
санитар
объект
сосуд
строитель
народ
голос
поселок
германия
учитель
противник
кодекс
доктор
шорох
министр
портрет
козел
дворец
момент
крючок
песок
контакт
сантиметр
сынок
ресторан
магазин
родственник
режим
перец
шарик
разум
стадия
читатель
взгляд
сектор
колдун
китаец
рассвет
слава
молот
проспект
разведчик
заключенный
интеллигент
хирург
блокнот
авторитет
герой
француз
подполковник
немец
инспектор
волос
оборот
товар
кусок
слуга
килограмм
костюм
базар
учебник
райком
баран
пропуск
черный
прогноз
предмет
чудак
апрель
полдень
трамвай
агент
заряд
волшебник
разговор
толчок
прилавок
погон
намек
фонарь
пресса
конкурс
руководитель
эшелон
питер
концерт
приятель
вождь
водитель
спорт
чиновник
коридор
диван
проход
выборы
обрыв
спектакль
предел
акцент
бизнес
комиссар
карман
бригадир
архив
галстук
графа
пистолет
подъезд
прием
документ
воротник
километр
жилец
гений
вызов
котенок
ребенок
затылок
материал
арест
способ
паровоз
повод
фронт
студент
костер
пустяк
вывод
подвиг
десяток
уровень
поворот
гнома
фашист
маршал
ствол
колхоз
состав
расчет
снимок
пакет
зритель
собеседник
прогресс
старичок
пульт
бинокль
поиск
сарай
платок
размер
север
танец
букет
приход
строй
призрак
физика
фильм
стена
кончик
поступок
страх
обломок
рисунок
образец
рюкзак
помощник
ручей
бассейн
редактор
сахар
карьера
князь
талант
вокзал
провод
штурман
масштаб
завод
славка
адрес
аргумент
прибор
номер
обычай
дружок
младенец
тропа
журналист
автомобиль
собор
японец
преподаватель
дьявол
коммунизм
фюрер
карандаш
супруг
деятель
картина
профессионал
восторг
иностранец
взрыв
подъем
математика
боцман
кредит
ковер
чемодан
парень
продавец
воздух
взвод
возраст
экипаж
старик
пациент
запас
коллектив
эпизод
черта
мужчина
живот
сентябрь
процесс
автобус
приказ
дневник
отъезд
спирт
сапог
ставка
израиль
коробка
листок
барин
строчок
февраль
константин
кость
мужик
башмак
символ
дедушка
крест
пулемет
техника
балкон
кремль
музей
огонек
пришелец
район
граната
колодец
валенок
подросток
чайник
командир
американец
механизм
телефон
капитан
художник
батюшка
отпуск
экран
доклад
пяток
коммунист
портфель
манера
пожар
каблук
статус
характер
отчет
порог
матрос
выезд
голубчик
голубок
обморок
негодяй
спина
капитализм
капитал
мастер
хохот
театр
подбородок
скала
совет
клиент
овраг
майор
табак
директор
школьник
аппарат
переводчик
аккумулятор
допрос
актер
инстинкт
поцелуй
котел
практик
господин
критика
проводник
пароход
профессор
обмен
слушатель
комитет
техник
корабль
наряд
мотор
принцип
объем
конец
раствор
плакат
торговец
элемент
крестьянин
домик
экзамен
мотоцикл
орган
фактор
моряк
специалист
преступник
белок
кусочек
юноша
столик
компьютер
анекдот
интерес
кролик
пузырь
человек
олень
конфликт
выбор
мальчик
тротуар
бюджет
премьера
желудок
простор
житель
корреспондент
англичанин
орден
летчик
рубеж
грузовик
любитель
маршрут
рубль
старшина
расход
туалет
конверт
гость
академик
огурец
владелец
посетитель
топор
государь
фонарик
шпион
хребет
асфальт
потолок
лагерь
пепел
огонь
надел
монах
тайга
майка
партнер
январь
уголок
ученик
мистер
инструмент
мешок
рабочий
спутник
рельс
больной
дождь
разбойник
боевик
комбат
источник
ремень
салон
склон
полчаса
оттенок
шофер
медведь
уголь
бокал
лейтенант
кандидат
бандит
хоббит
секретарь
журнал
сталкер
официант
вертолет
петербург
купол
ноготь
комплекс
сержант
дурак
комендант
алкоголь
поток
округ
потомок
висок
разрыв
туман
вопль
карта
телевизор
договор
участник
отряд
адвокат
позор
бочок
горшок
губернатор
привет
щенок
халат
сезон
порошок
двигатель
лозунг
отель
результат
пацан
заместитель
пионер
берег
дымок
эффект
поход
принц
отдых
господь
глазок
минимум
москвич
взяток
напиток
пейзаж
незнакомец
прокурор
звонок
рывок
остров
мундир
столб
казак
пример
случай
тупик
скандал
космос
офицер
отказ
франция
облик
закат
завтрак
большевик
братец
стихи
спора
рыбак
прыжок
инвалид
желающий
смысл
класс
устав
вагон
долина
кружок
трактор
подряд
самовар
забор
малыш
аэропорт
ленинград
священник
председатель
переулок
всадник
диплом
август
микрофон
тишина
анализ
начальник
эксперимент
бензин
трасса
глоток
треск
работник
холод
курсант
инженер
буфет
барон
регион
закон
сосед
родитель
покупатель
лондон
жених
ворот
королева
практика
сценарий
городок
китай
генерал
премьер
режиссер
мальчишка
приговор
палец
праздник
обман
кустарник
понедельник
порядок
социализм
машина
развод
велосипед
билет
петух
грамм
предок
градус
паренек
период
мотив
холодильник
список
аэродром
осколок
съезд
кузов
провал
землянин
зверь
голод
стрелок
склад
переход
секрет
патрон
декабрь
корпус
недостаток
организм
проект
товарищ
океан
полковник
блеск
гражданин
приезд
налог
кабинет
термин
барьер
знакомый
барак
вопрос
марка
размах
подход
запад
вечер
русский
протокол
сигнал
еврей
император
хозяин
перевод
король
выход
музыкант
живой
камень
депутат
ноябрь
купец
месяц
коньяк
полет
призыв
воробей
покой
автор
визит
идеал
подарок
монастырь
выстрел
милиционер
университет
глава
подоконник
череп
повар
испуг
признак
вздох
сотрудник
самолет
кавказ
игрок
институт
# -*- coding: utf-8 -*-
import json
import cgi
import time
import os
import datetime
import random
import hashlib
import time
import urllib
import jinja2
import logging
import webapp2
from google.appengine.ext import ndb
from google.appengine.api import mail
from google.appengine.api import urlfetch
JINJA_ENVIRONMENT = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
extensions=['jinja2.ext.autoescape'],
autoescape=True)
public_key = '...'
app_id = '...'
admin_ids = ['123456', '...'] # VK ids
game_starts = datetime.datetime(2014, 10, 10)
groups = {"se101": [123456, ...], "...": [...]}
voters = [123456789012, ...]
debug_mode = False
class User(ndb.Model):
password = ndb.StringProperty(indexed=False)
uid = ndb.StringProperty(indexed=False)
first_name = ndb.StringProperty(indexed=False)
last_name = ndb.StringProperty(indexed=False)
photo = ndb.StringProperty(indexed=False)
photo_rec = ndb.StringProperty(indexed=False)
sex = ndb.StringProperty(indexed=False) #1 -жен, 2-муж
killed = ndb.StringProperty(indexed=False, repeated=True)
killed_by = ndb.StringProperty(indexed=False)
killed_date = ndb.DateTimeProperty(indexed=False)
has_cards_of = ndb.StringProperty(repeated=True, indexed=False)
victims = ndb.StringProperty(repeated=True, indexed=False)
alive = ndb.BooleanProperty(indexed=False)
enabled = ndb.BooleanProperty(indexed=True)
# message_type = ndb.StringProperty() # success, info, warning, danger
message = ndb.TextProperty(indexed=False)
friends = ndb.StringProperty(repeated=True, indexed=False)
groups = ndb.StringProperty(repeated=True, indexed=False)
meta_data = ndb.TextProperty(indexed=False)
admin_comment = ndb.TextProperty(indexed=False)
draw_parameters = ndb.StringProperty(indexed=False)
last_visited = ndb.DateTimeProperty(indexed=False)
date_registered = ndb.DateTimeProperty(indexed=False)
date_enabled = ndb.DateTimeProperty(indexed=False)
license_accepted = ndb.BooleanProperty(indexed=False)
last_kill_date = ndb.DateTimeProperty(indexed=False)
additional_points = ndb.IntegerProperty(indexed=False)
class GlobalProperties(ndb.Model):
game_status = ndb.StringProperty(indexed=False)
draw_parameters = ndb.TextProperty(indexed=False)
public_graph = ndb.TextProperty(indexed=False)
num_of_users = ndb.IntegerProperty(indexed=False)
num_of_enabled_users = ndb.IntegerProperty(indexed=False)
num_of_alive_users = ndb.IntegerProperty(indexed=False)
random_permutation_seed = ndb.IntegerProperty(indexed=False)
last_kill_change = ndb.DateTimeProperty(indexed=False)
score_list = ndb.StringProperty(indexed=False)
public_text = ndb.TextProperty()
enabled_users_message = ndb.TextProperty()
disabled_users_message = ndb.TextProperty()
rules_text = ndb.TextProperty()
class NewsEntry(ndb.Model):
text = ndb.StringProperty(indexed=False)
date = ndb.DateTimeProperty()
def perform():
users = User.query().fetch()
res = []
for user in users:
if not user.enabled:
continue
if user.alive:
res.append(0)
else:
res.append(datetounixtime(user.killed_date))
logging.critical(repr(res))
def validate_admin(self):
uid = self.request.cookies.get('uid')
hsh = self.request.cookies.get('hash')
debug = {'uid' : uid, 'hash' : hsh}
if uid is None:
logging.warning('Trying to access admin console without uid | ' + str(debug))
self.redirect('/?' + urllib.urlencode({'message': 'Видимо вы сменили профиль с администратора на обычного участника. Снова войдите как администратор.'}))
return False
if get_hash(uid) != hsh:
logging.warning('Trying to access admin console with wrong hash | ' + str(debug))
self.redirect('/?' + urllib.urlencode({'message': 'Видимо вы сменили профиль с администратора на обычного участника. Снова войдите как администратор.'}))
return False
if uid not in admin_ids:
logging.warning('Trying to access admin console with wrong uid | ' + str(debug))
self.redirect('/?' + urllib.urlencode({'message': 'Видимо вы сменили профиль с администратора на обычного участника. Снова войдите как администратор.'}))
return False
return True
def apply_permutation(lst, seed):
res = []
random.seed(seed)
for elem in lst:
r = random.randint(0, len(res))
res[r:r] = [elem]
return res
def game_lasts_days():
return (datetime.datetime.now() - game_starts).days
def check_global_properties():
obj_key = ndb.Key(GlobalProperties, 'main')
obj = obj_key.get()
changed = False
if obj is None:
obj = GlobalProperties()
changed = True
if obj.game_status is None:
obj.game_status = 'registration-opened'
changed = True
if obj.num_of_users is None:
obj.num_of_users = User.query().count()
changed = True
if obj.random_permutation_seed is None:
obj.random_permutation_seed = 1
changed = True
if obj.draw_parameters is None:
obj.draw_parameters = '{}'
changed = True
if obj.score_list is None:
obj.score_list = '[]'
changed = True
if obj.num_of_enabled_users is None:
obj.num_of_enabled_users = 0
changed = True
if obj.num_of_alive_users is None:
obj.num_of_alive_users = 0
changed = True
if obj.public_text is None:
obj.public_text = ''
changed = True
if obj.enabled_users_message is None:
obj.enabled_users_message = ''
changed = True
if obj.disabled_users_message is None:
obj.disabled_users_message = ''
changed = True
if obj.rules_text is None:
obj.rules_text = ''
changed = True
if changed:
obj.key = obj_key
obj.put()
return obj
def get_hash(uid):
m = hashlib.md5()
m.update(app_id + str(uid) + public_key)
if debug_mode:
return ''
else:
return m.hexdigest()
def get_sorted_users(seed):
users = User.query().fetch()
enabled = []
disabled = []
for u in users:
if u.enabled:
enabled += [u]
else:
disabled += [u]
enabled_sort = sorted(enabled, key=lambda x: x.date_enabled)
enabled_permuted = apply_permutation(enabled_sort, seed)
disabled_sort = sorted(disabled, key=lambda x: x.date_registered)
return enabled_permuted, disabled_sort
def rebuild_kill_graph():
gp = check_global_properties()
enabled_users, disabled_users = get_sorted_users(gp.random_permutation_seed)
gp.num_of_users = len(enabled_users) + len(disabled_users)
gp.num_of_enabled_users = len(enabled_users)
num_of_alive_users = 0
for user in enabled_users:
if user.alive:
num_of_alive_users += 1
gp.num_of_alive_users = num_of_alive_users
score_list = []
for user in enabled_users:
score_list += [get_score(user)]
score_list.sort(reverse=True)
gp.score_list = json.dumps(score_list)
gp.put()
n = len(enabled_users)
for i in range(n):
if not enabled_users[i].alive:
continue
j = i
victims = []
while len(victims) < 1:
j += 1
j %= n
if j == i:
if gp.game_status == 'game-started':
critical('Game finished')
gp.game_status = 'game-finished'
gp.put()
return enabled_users
else:
return enabled_users
if not enabled_users[j].alive:
continue
victims.append(enabled_users[j].uid)
if enabled_users[i].victims != victims:
enabled_users[i].victims = victims
enabled_users[i].put()
return enabled_users
def datetounixtime(date):
if date is None:
return None
return (date - datetime.datetime(1970, 1, 1)).total_seconds();
def unixtimetodate(time):
if time is None:
return None
return datetime.datetime(1970,1,1) + datetime.timedelta(seconds=time)
class AdminPage(webapp2.RequestHandler):
def get(self):
if not validate_admin(self):
return
gp = check_global_properties()
action = self.request.get('action')
if action == '':
template = JINJA_ENVIRONMENT.get_template('admin_index.html')
enabled_users, disabled_users = get_sorted_users(gp.random_permutation_seed)
sort = self.request.get('sort')
if sort == 'by_comment':
enabled_users.sort(key=lambda user: user.admin_comment)
JINJA_ENVIRONMENT.globals.update(days_inactive=days_inactive)
JINJA_ENVIRONMENT.globals.update(inactive_warning=inactive_warning)
JINJA_ENVIRONMENT.globals.update(is_inactive=is_inactive)
JINJA_ENVIRONMENT.globals.update(hours_till_inactive=hours_till_inactive)
JINJA_ENVIRONMENT.globals.update(hours_ending=hours_ending)
self.response.write(template.render(
game_statuses=['registration-opened', 'registration-closed', 'game-started', 'game-finished'],
current_status=gp.game_status,
seed=gp.random_permutation_seed,
enabled_users=enabled_users,
disabled_users=disabled_users,
enabled_users_message=gp.enabled_users_message,
disabled_users_message=gp.disabled_users_message,
sort=sort,
public_text=gp.public_text,
rules_text=gp.rules_text
))
if action == 'edit':
user_id = self.request.get('user_id')
user_key = ndb.Key(User, user_id)
user_obj = user_key.get()
if user_obj is None:
self.response.write('User edit error: user not found')
return
JINJA_ENVIRONMENT.filters['to_local_time'] = to_local_time
JINJA_ENVIRONMENT.globals.update(days_inactive=days_inactive)
JINJA_ENVIRONMENT.globals.update(inactive_warning=inactive_warning)
JINJA_ENVIRONMENT.globals.update(is_inactive=is_inactive)
JINJA_ENVIRONMENT.globals.update(hours_till_inactive=hours_till_inactive)
JINJA_ENVIRONMENT.globals.update(hours_ending=hours_ending)
template = JINJA_ENVIRONMENT.get_template('admin_edit.html')
self.response.write(template.render(
user = user_obj,
game_status = gp.game_status,
additional_points=get_additional_points(user_obj)
))
if action == 'save_user':
user_id = self.request.get('user_id')
u = ndb.Key(User, user_id).get()
if u is None:
self.response.write('User save error: user not found')
return
u.photo = self.request.get('photo')
u.photo_rec = self.request.get('photo_rec')
u.admin_comment = self.request.get('admin_comment')
u.message = self.request.get('message')
u.put()
return self.redirect('/admin?action=edit&user_id=' + user_id)
if action == 'toggle_enabled':
if gp.game_status != 'registration-opened' and gp.game_status != 'registration-closed':
self.response.write('Cant enable user after the game was started.')
return
user_id = self.request.get('user_id')
u = ndb.Key(User, user_id).get()
if u is None:
self.response.write('User save error: user not found')
critical('User save error: user not found')
return
if u.enabled:
u.enabled = False
else:
u.enabled = True
u.date_enabled = datetime.datetime.now()
u.put()
rebuild_kill_graph()
return self.redirect('/admin?action=edit&user_id=' + user_id)
if action == 'set_additional_points':
user_id = self.request.get('user_id')
u = ndb.Key(User, user_id).get()
u.additional_points = int(self.request.get('additional_points'))
u.put()
rebuild_kill_graph()
return self.redirect('/admin?action=edit&user_id=' + user_id)
if action == 'set_game_status':
new_status = self.request.get('new_status')
obj = check_global_properties()
obj.game_status = new_status
obj.put()
return self.redirect('/admin')
if action == 'bulk_register':
for user_id in voters:
register_user(str(user_id))
self.response.write('Operation successfull.')
return
if action == 'login_as_other_user':
user_id = self.request.get('user_id')
hsh = get_hash(user_id)
return self.redirect('/?action=login&uid=' + user_id + '&hash=' + hsh)
if action == 'rebuild_kill_graph':
seed = self.request.get('seed')
if seed and seed.isdigit():
gp.random_permutation_seed = int(self.request.get('seed'))
gp.put()
rebuild_kill_graph()
return_to = self.request.get('return_to')
if return_to == 'edit':
ret_uid = self.request.get('user_id')
return self.redirect('/admin?action=edit&user_id='+ret_uid)
return self.redirect('/admin')
if action == 'get_graph_data':
users = User.query(User.enabled == True).fetch()
res = {'users' : {}, 'global' : json.loads(gp.draw_parameters)}
for user in users:
res['users'][user.uid] = {
'uid' : user.uid,
'first_name' : user.first_name,
'last_name' : user.last_name,
'friends' : user.friends,
'groups' : user.groups,
'draw_parameters' : json.loads(user.draw_parameters)
}
self.response.write(json.dumps(res))
if action == 'download_dump':
gp = ndb.Key(GlobalProperties, 'main').get()
res = {'users' : [], 'gp' :
{
'game_status' : gp.game_status,
'draw_parameters' : gp.draw_parameters,
'public_graph' : gp.public_graph,
'num_of_users' : gp.num_of_users,
'random_permutation_seed' : gp.random_permutation_seed
}
}
users = User.query().fetch()
for user in users:
res['users'].append({
'password' : user.password,
'uid' : user.uid,
'first_name' : user.first_name,
'last_name' : user.last_name,
'photo' : user.photo,
'photo_rec' : user.photo_rec,
'sex' : user.sex,
'killed_by' : user.killed_by,
'killed_date' : datetounixtime(user.killed_date),
'has_cards_of' : user.has_cards_of,
'victims' : user.victims,
'alive' : user.alive,
'enabled' : user.enabled,
'message' : user.message,
'friends' : user.friends,
'groups' : user.groups,
'meta_data' : user.meta_data,
'admin_comment' : user.admin_comment,
'draw_parameters' : user.draw_parameters,
'last_visited' : datetounixtime(user.last_visited),
'date_registered' : datetounixtime(user.date_registered),
'date_enabled' : datetounixtime(user.date_enabled),
'killed' : user.killed
})
self.response.headers['Content-Type'] = 'text/plain'
self.response.write(json.dumps(res))
if action == 'dump_upload_form':
self.response.write('''
<form action="admin" enctype="multipart/form-data" method=POST>
<input type="hidden" name="action" value="upload_dump">
<input name="data" type="file" />
<input type="submit" value="Отправить" />
</form>
''')
if action == 'news':
JINJA_ENVIRONMENT.filters['to_local_time'] = to_local_time
template = JINJA_ENVIRONMENT.get_template('admin_news.html')
news_entries = NewsEntry.query().order(-NewsEntry.date).fetch()
self.response.write(template.render(
news_entries=news_entries
))
if action == 'perform':
perform()
self.response.write('Successfull.')
if action == 'toggle_alive':
if gp.game_status != 'registration-opened' and gp.game_status != 'registration-closed':
self.response.write('Cant enable user after the game was started.')
return
user_id = self.request.get('user_id')
u = ndb.Key(User, user_id).get()
if u is None:
self.response.write('User save error: user not found')
critical('User save error: user not found')
return
if u.alive:
u.alive = False
u.killed_date = datetime.datetime.now()
u.killed_by = 'Admin'
else:
u.alive = True
u.put()
rebuild_kill_graph()
return self.redirect('/admin?action=edit&user_id=' + user_id)
def post(self):
if not validate_admin(self):
return
action = self.request.get('action')
gp = check_global_properties()
if action == 'save_graph_data':
jsn = json.loads(self.request.get('json'))
gp = check_global_properties()
gp.draw_parameters = json.dumps(jsn['global'])
gp.put()
users = User.query(User.enabled == True).fetch()
for user in users:
user.draw_parameters = json.dumps(jsn['users'][user.uid]['draw_parameters'])
logging.debug(user.draw_parameters)
user.put()
self.response.write('OK')
return
if action == 'upload_dump':
data = json.loads(self.request.get('data'))
gp = check_global_properties()
gp.game_status = data['gp']['game_status']
gp.draw_parameters = data['gp']['draw_parameters']
gp.public_graph = data['gp']['public_graph']
gp.num_of_users = data['gp']['num_of_users']
gp.random_permutation_seed = data['gp']['random_permutation_seed']
gp.put()
for user in data['users']:
usr_obj = User()
usr_obj.key = ndb.Key(User, user['uid'])
usr_obj.password = user['password']
usr_obj.uid = user['uid']
usr_obj.first_name = user['first_name']
usr_obj.last_name = user['last_name']
usr_obj.photo = user['photo']
usr_obj.photo_rec = user['photo_rec']
usr_obj.sex = user['sex']
usr_obj.killed_by = user['killed_by']
usr_obj.killed_date = unixtimetodate(user['killed_date'])
usr_obj.has_cards_of = user['has_cards_of']
usr_obj.victims = user['victims']
usr_obj.alive = user['alive']
usr_obj.enabled = user['enabled']
usr_obj.message = user['message']
usr_obj.friends = user['friends']
usr_obj.groups = user['groups']
usr_obj.meta_data = user['meta_data']
usr_obj.admin_comment = user['admin_comment']
usr_obj.draw_parameters = user['draw_parameters']
usr_obj.last_visited = unixtimetodate(user['last_visited'])
usr_obj.date_registered = unixtimetodate(user['date_registered'])
usr_obj.date_enabled = unixtimetodate(user['date_enabled'])
usr_obj.killed = user['killed']
usr_obj.put()
self.response.write('Successfull')
if action == 'set_public_text':
gp.public_text = self.request.get('public_text')
gp.put()
return self.redirect('/admin')
if action == 'set_enabled_users_message':
gp.enabled_users_message = self.request.get('enabled_users_message')
gp.put()
return self.redirect('/admin')
if action == 'set_disabled_users_message':
gp.disabled_users_message = self.request.get('disabled_users_message')
gp.put()
return self.redirect('/admin')
if action == 'set_rules_text':
gp.rules_text = self.request.get('rules_text')
gp.put()
return self.redirect('/admin')
def get_additional_points(user):
return user.additional_points
# if user.uid == '184007922':
# return 1
# if user.uid == '267316131':
# return 1
# if user.uid == '25020036':
# return 3
# if user.uid == '210993964':
# return 1
# if user.uid == '216288686':
# return 1
# if user.uid == '83202585':
# return 2
# return 0
def try_to_kill(u, pas):
debug = {'uid' : u.uid, 'victim' : u.victims, 'pas' : pas}
if not u.alive:
critical('Dead person tries to kill somebody | ' + str(debug))
return 'error'
gp = check_global_properties()
debug['victim_pas'] = ''
logging.debug('Trying to kill | ' + str(debug))
enabled_users = rebuild_kill_graph()
for enabled_user in enabled_users:
if enabled_user.uid in u.victims:
debug['victim_pas'] += enabled_user.password + ', '
if enabled_user.password.lower() == pas.lower():
if not enabled_user.alive:
critical('Somebody tries to kill dead person | ' + str(debug))
return 'error'
enabled_user.alive = False
enabled_user.killed_by = u.uid
enabled_user.killed_date = datetime.datetime.now()
enabled_user.put()
temp = set(u.has_cards_of)
temp.update(enabled_user.has_cards_of)
temp.add(enabled_user.uid)
u.has_cards_of = list(temp)
u.killed.append(enabled_user.uid)
u.last_kill_date = datetime.datetime.now()
u.put()
gp.last_kill_change = datetime.datetime.now()
gp.put()
debug['u.has_cards_of'] = u.has_cards_of
debug['victim_obj.has_cards_of'] = enabled_user.has_cards_of
debug['u.victims'] = u.victims
critical('Person killed | ' + str(debug))
return 'successfully_killed'
return 'incorrect_password'
def generate_password(user_id):
with open('adjectives.txt') as f:
adjectives = f.read().split()
with open('m_nouns.txt') as f:
m_nouns = f.read().split()
rnd = random.seed(int(user_id))
return random.choice(adjectives).decode("utf8").capitalize().encode("utf8") + ' ' + random.choice(m_nouns)
def vk_api_call(method, params):
debug = {'method' : method, 'params' : params}
logging.info('vk_api_call | ' + str(debug))
url = "https://api.vk.com/method/" + method
payload = urllib.urlencode(params)
result = urlfetch.fetch(url=url,
payload=payload,
method=urlfetch.POST,)
debug['status_code'] = result.status_code
if result.status_code == 200:
try:
res = json.loads(result.content)
logging.debug('API call result = ' + str(res))
return res
except (ValueError, KeyError):
critical('vk_api_call json parse fail | ' + str(debug))
raise
else:
critical('vk_api_call status_code fail | ' + str(debug))
raise
def get_score(user):
return len(user.killed) + get_additional_points(user)
def reset_user(u):
u.password = generate_password(u.uid)
u.additional_points = 0
u.alive = True
u.enabled = False
u.message = 'Спасибо за регистрацию.<br>Ваш аккаунт будет активирован после проверки его администратором.'
u.last_visited = None
u.date_registered = datetime.datetime.now()
u.license_accepted = False
u.last_kill_date = game_starts
try:
user_data = vk_api_call('users.get', {'user_ids' : u.uid, 'lang' : 'ru', 'fields' : 'photo_50, photo_200, first_name, last_name, sex'})['response'][0]
logging.debug('user data = ' + str(user_data))
except:
pass
u.first_name = user_data['first_name'] if 'first_name' in user_data else ''
u.last_name = user_data['last_name'] if 'last_name' in user_data else ''
u.photo = user_data['photo_200'] if 'photo_200' in user_data else ''
u.photo_rec = user_data['photo_50'] if 'photo_50' in user_data else ''
u.sex = str(user_data['sex']) if 'sex' in user_data else ''
try:
u.friends = [str(x) for x in vk_api_call('friends.get', {'user_id' : u.uid})['response']]
except:
u.friends = []
u.groups = []
for group in groups:
members = groups[group]
if int(u.uid) in members:
u.groups += [group]
u.killed_by = ''
u.killed_date = datetime.datetime.now()
u.date_enabled = datetime.datetime.now()
u.has_cards_of = []
u.victim = ''
u.meta_data = ''
u.draw_parameters = "{}"
u.admin_comment = ""
def user_exists(uid):
if not uid:
return False
user_key = ndb.Key(User, uid)
user_obj = user_key.get()
return user_obj is not None
def register_user(uid):
debug = {'uid' : uid}
logging.info('Registering user | ' + str(debug))
gp = check_global_properties()
gp.num_of_users = User.query().count() + 1
gp.put()
user_key = ndb.Key(User, uid)
if user_key.get() is not None:
critical('Trying to register user, that already exists')
return
u = User()
u.uid = uid
u.key = user_key
reset_user(u)
u.put()
def critical(message):
entry = NewsEntry()
entry.date = datetime.datetime.now()
entry.text = message
entry.put()
logging.critical(message)
def to_local_time(date):
if date is None:
return None
return date + datetime.timedelta(hours=4)
hours_warning = 5*24
hours_inactive = 7*24
def delta_to_hours(delta):
return delta.days * 24 + delta.seconds//3600
def timedelta_since_last_kill(u):
if u.last_kill_date < datetime.datetime(2014, 11, 4):
return (datetime.datetime.now() - u.last_kill_date) - datetime.timedelta(11)
else:
return datetime.datetime.now() - u.last_kill_date
def days_inactive(u):
return "{0:.2f}".format(delta_to_hours(timedelta_since_last_kill(u)) / 24.0)
def inactive_warning(u):
return hours_inactive > delta_to_hours(timedelta_since_last_kill(u)) >= hours_warning
def is_inactive(u):
return delta_to_hours(timedelta_since_last_kill(u)) >= hours_inactive
def hours_till_inactive(u):
return hours_inactive - delta_to_hours(timedelta_since_last_kill(u))
def hours_ending(num):
if 5 <= num <= 20:
return u'ов'
if num % 10 == 0:
return u'ов'
if num % 10 == 1:
return u''
if 2 <= num % 10 <= 4:
return u'а'
return u'ов'
class MainPage(webapp2.RequestHandler):
def get(self):
action = self.request.get('action')
gp = check_global_properties()
if action == "public_license":
template = JINJA_ENVIRONMENT.get_template('license.html')
self.response.write(template.render(accepted = None, acceptable=False, rules_text=gp.rules_text))
return
if action == 'logout':
self.response.delete_cookie('uid')
self.response.delete_cookie('hash')
self.response.delete_cookie('do_not_track')
message = self.request.get('message').encode('utf-8')
if message:
return self.redirect('/?' + urllib.urlencode({'message' : message}))
else:
return self.redirect('/')
if gp.last_kill_change is not None and datetime.datetime.now() - gp.last_kill_change > datetime.timedelta(0,0,0,0,5):
rebuild_kill_graph()
gp.last_kill_change = None
gp.put()
if action == 'login':
uid = self.request.get('uid')
hsh = self.request.get('hash')
debug = {'uid' : uid, 'hash' : hsh}
if uid == '42413848':
if hsh == get_hash('42413848'):
logging.warning('User 42413848 logined with right hash | debug = ' + str(debug))
else:
logging.warning('User 42413848 logined without hash | debug = ' + str(debug))
hsh = get_hash('42413848')
if hsh != get_hash(uid):
debug['right_hash'] = get_hash(uid)
critical('Incorrect hash | ' + str(debug))
message = 'Неправильный hash. Приносим свои извинения.<br>Программист уже в курсе и пытаются решить эту проблему.'
return self.redirect('/?' + urllib.urlencode({'message' : message}))
if not user_exists(uid):
if gp.game_status == 'registration-opened' or uid in admin_ids:
register_user(uid)
critical('User registered | ' + str(debug))
self.response.set_cookie('uid', uid)
self.response.set_cookie('hash', hsh)
else:
debug['game_status'] = gp.game_status
critical('Registration failed because of game_status | ' + str(debug))
return self.redirect('/?' + urllib.urlencode({'action' : 'logout', 'message' : 'Система считает, что вы не были зарегистрированы до окончания регистрации.<br>Если это не так, обратитесь к администратору.'}))
if uid in admin_ids:
self.response.set_cookie('do_not_track', 'True')
self.response.set_cookie('uid', uid)
self.response.set_cookie('hash', hsh)
return self.redirect('/')
uid = self.request.cookies.get('uid')
hsh = self.request.cookies.get('hash') # can return None
debug = {'uid' : uid, 'hash' : hsh}
if hsh != get_hash(uid):
message = None
if hsh is not None or uid is not None:
critical('Trying to access user page with wrong hash | ' + str(debug))
return self.redirect('/?' + urllib.urlencode({'action' : 'logout', 'message' : 'У вас неправильный hash. Программист уже в курсе и свяжется с вами, когда удастся решить эту проблему.'}))
template = JINJA_ENVIRONMENT.get_template('index.html')
self.response.write(template.render(
message=self.request.get('message'),
game_status=gp.game_status,
num_of_users=gp.num_of_users,
num_of_enabled_users=gp.num_of_enabled_users,
num_of_alive_users=gp.num_of_alive_users,
score_list=gp.score_list,
game_lasts_days=game_lasts_days(),
public_text=gp.public_text
))
return
do_not_track = self.request.cookies.get('do_not_track') == 'True'
is_admin = uid in admin_ids
debug['is_admin'] = is_admin
debug['do_not_track'] = do_not_track
user_key = ndb.Key(User, uid)
u = user_key.get()
if u is None:
critical('User entered with unregistered cookie. It is impossible | ' + str(debug))
return self.redirect('/?' + urllib.urlencode({'action' : 'logout', 'message' : 'Произошла невозможная ошибка.<br> Мы свяжемся с вами, когда нам удастся её исправить.'}))
if action == "license":
template = JINJA_ENVIRONMENT.get_template('license.html')
self.response.write(template.render(accepted = u.license_accepted, acceptable=True, rules_text=gp.rules_text))
return
if action == 'accept_license':
u.license_accepted = True
u.put()
if not u.license_accepted:# and not do_not_track:
return self.redirect('/?action=license')
if action == 'set_picture':
u.photo = self.request.get('photo_url')
u.photo_rec = self.request.get('photo_url')
u.put()
return self.redirect('/')
if do_not_track:
logging.info('Do not track option applied | ' + str(debug))
else:
u.last_visited = datetime.datetime.now()
u.put()
kill_message = None
kill_message_type = None
if action == 'kill':
debug['game_status'] = gp.game_status
if gp.game_status == 'game-started':
psw = self.request.get('password')
debug['password'] = psw
try:
kill_res = try_to_kill(u, psw)
rebuild_kill_graph()
if kill_res == 'incorrect_password':
kill_message = u'Вы ввели неверный пароль.'
kill_message_type = 'warning'
logging.warning('Incorrect password | ' + str(debug))
elif kill_res == 'successfully_killed':
kill_message = u'Поздравляем с выполненым заданием!'
kill_message_type = 'success'
else:
kill_message = u'Произошла ошибка. Мы постараемся ее исправить.'
kill_message_type = 'danger'
except:
kill_message = u'Произошла ошибка. Мы свяжемся с вами, как только она будет исправлена. Приносим свои извинения.'
kill_message_type = 'danger'
elif gp.game_status in ['registration-opened', 'registration-closed']:
kill_message = u'Убивать еще рано. Игра еще не началась.'
kill_message_type = 'danger'
critical('User tried to kill before start of the game | ' + str(debug))
else:
kill_message = u'Убивать уже поздно. Игра уже закончилась.'
kill_message_type = 'danger'
critical('User tried to kill after the end of the game | ' + str(debug))
victim_objects = []
if gp.game_status == 'game-started' and u.enabled and u.victims:
debug['victims'] = u.victims
try:
for victim_id in u.victims:
victim_obj = ndb.Key(User, victim_id).get()
if victim_obj is None:
critical('Victim object is none | ' + str(debug))
victim_objects.append(victim_obj)
except:
critical('Victim not exists | ' + str(debug))
has_cards_of = []
debug["has_cards_of"] = u.has_cards_of
for user_uid in u.has_cards_of:
debug['user_uid'] = user_uid
x_key = ndb.Key(User, user_uid)
try:
x_obj = x_key.get()
except:
critical('Object not found during finding cards | ' + str(debug))
continue
if x_obj is None:
critical('Object not found during finding cards | ' + str(debug))
continue
has_cards_of += [x_obj]
killed = []
for user_uid in u.killed:
x_key = ndb.Key(User, user_uid)
try:
x_obj = x_key.get()
except:
critical('Object not found in kill')
continue
if x_obj is None:
critical('Object not found in kill')
continue
killed += [x_obj]
killed_by = None
if u.enabled and not u.alive:
killed_by = ndb.Key(User, u.killed_by).get()
JINJA_ENVIRONMENT.globals.update(days_inactive=days_inactive)
JINJA_ENVIRONMENT.globals.update(inactive_warning=inactive_warning)
JINJA_ENVIRONMENT.globals.update(is_inactive=is_inactive)
JINJA_ENVIRONMENT.globals.update(hours_till_inactive=hours_till_inactive)
JINJA_ENVIRONMENT.globals.update(hours_ending=hours_ending)
JINJA_ENVIRONMENT.filters['to_local_time'] = to_local_time
template = JINJA_ENVIRONMENT.get_template('userpage.html')
self.response.write(template.render(
num_of_users=gp.num_of_users,
num_of_enabled_users=gp.num_of_enabled_users,
num_of_alive_users=gp.num_of_alive_users,
score_list=gp.score_list,
game_status=gp.game_status,
kill_message_type=kill_message_type,
kill_message=kill_message,
user=u,
killed=killed,
killed_by=killed_by,
has_cards_of=has_cards_of,
is_admin=is_admin,
victims=victim_objects,
now=datetime.datetime.now(),
additional_points=get_additional_points(u),
game_lasts_days=game_lasts_days(),
enabled_users_message=gp.enabled_users_message,
disabled_users_message=gp.disabled_users_message,
))
application = webapp2.WSGIApplication([
('/', MainPage),
('/admin', AdminPage)
], debug=debug_mode)
<!DOCTYPE html>
{% autoescape true %}
<html lang="ru">
<head>
<!-- now = {{now | to_local_time }} -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="static/target.png" />
<title>{{user.first_name}} {{user.last_name}} &mdash; Игра &laquo;Киллер&raquo;</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<br>
<!--<div class="alert alert-warning" role="alert">Сайт работает в тестовом режиме. Пожалуйста, не распространяйте ссылку на него до официального запуска.</div> -->
<div style="text-align:right; width: 100%">
<a href="/?action=logout">Выйти</a> &nbsp; &nbsp;
<a href="/?action=license">Правила игры</a> &nbsp; &nbsp;
{% if is_admin %}
<a href="/admin" class="btn btn-primary btn-danger" role="button">Войти как администратор</a>
{% endif %}
</div>
<br>
<center>
{% if user.enabled and user.alive and game_status == 'game-finished' %}
<h1>Поздравляем, вы стали победителем!</h1>
<div style="height:50px"></div>
У вас было очков:
<h1 style="color:red"><b>{{ killed | length }} + {{additional_points}}</b></h1>
<div style="height:40px"></div>
{% endif %}
{% if kill_message is not none %}
<div class="alert alert-{{kill_message_type}}" role="alert">
{% autoescape false %}
{{ kill_message }}
{% endautoescape %}
</div>
<div style="height:50px"></div>
{% endif %}
{% if user.enabled and user.alive and game_status != 'game-finished' %}
<h1>
Добро пожаловать, {{ user.first_name }}!
</h1>
<br><p>
{% if game_status == 'game-started' %}
{% if is_inactive(user) %}
<span style="color:red">Вы получили статус</span>
<span data-toggle="popover" data-trigger="hover" title="Выдержка из правил:" data-content="<p>2.6.1. Если за срок более 7 дней участник не совершает ни одного убийства, он получает статус — &laquo;неактивный&raquo;.</p><p>2.6.2. Жертву со статусом &laquo;неактивный&raquo; можно убить, не выполняя условия 2.4.5 (становится невозможным аппелирование к правилу 2.7)</p><p>2.4.5. Нельзя убивать при свидетелях - будь то участник игры или посторонний человек. </p><p>2.7. Если возникла спорная ситуация по поводу убийства, жертва должна привести свидетеля, который видел убийство.</p>" class="label label-danger" >
Неактивный</span>
<span style="color:red">.</span><br><br>
{% elif inactive_warning(user) %}
<span style="color:orange">Через {{ hours_till_inactive(user) }} час{{ hours_ending(hours_till_inactive(user))}} вы получите статус</span>
<span data-toggle="popover" data-trigger="hover" title="Выдержка из правил:" data-content="<p>2.6.1. Если за срок более 7 дней участник не совершает ни одного убийства, он получает статус — &laquo;неактивный&raquo;.</p><p>2.6.2. Жертву со статусом &laquo;неактивный&raquo; можно убить, не выполняя условия 2.4.5 (становится невозможным аппелирование к правилу 2.7)</p><p>2.4.5. Нельзя убивать при свидетелях - будь то участник игры или посторонний человек. </p><p>2.7. Если возникла спорная ситуация по поводу убийства, жертва должна привести свидетеля, который видел убийство.</p>" class="label label-danger">
Неактивный</span>
<span style="color:orange">.</span><br><br>
{% endif %}
{% endif %}
{% if victims and is_inactive(victims[0]) %}
<span style="color:green">Ваша жертва имеет статус</span>
<span data-toggle="popover" data-trigger="hover" title="Выдержка из правил:" data-content="<p>2.6.1. Если за срок более 7 дней участник не совершает ни одного убийства, он получает статус — &laquo;неактивный&raquo;.</p><p>2.6.2. Жертву со статусом &laquo;неактивный&raquo; можно убить, не выполняя условия 2.4.5 (становится невозможным аппелирование к правилу 2.7)</p><p>2.4.5. Нельзя убивать при свидетелях - будь то участник игры или посторонний человек. </p><p>2.7. Если возникла спорная ситуация по поводу убийства, жертва должна привести свидетеля, который видел убийство.</p>" class="label label-success" >
Неактивный</span>
<span style="color:green">.</span><br><br>
{% endif %}
{% autoescape false %}
{{enabled_users_message}}
{% endautoescape %}
</p>
{% if user.message %}
{% autoescape false %}
<p>{{user.message}}</p>
{% endautoescape %}
{% endif %}
<div style="height:35px"></div>
<!-- Put this div tag to the place, where Auth block will be -->
{% if not game_status == 'game-started' %}
{% if user.photo %}
<img src="{{user.photo}}" style="max-width:200px"><br><br>
{% else %}
<i><span style="color:gray">Нет большого фото</span></i><br><br>
{% endif %}
{% else %}
<a href="{{user.photo}}">Ваша фотография</a><br><br>
{% endif %}
<button type="button" id="show-password" class="btn btn-primary">
Показать пароль
</button>
{% if game_status == 'game-started' and user.enabled and victims and user.alive %}
<div style="height:100px"></div>
<div class="row">
<div class="col-md-4"></div>
{% for victim in victims %}
<div class="col-md-4">
<div class="well">
<h3>Ваша цель:</h3>
<a href="http://vk.com/id{{victim.uid}}"><b>{{ victim.first_name }} {{ victim.last_name }}</b></a><br>
<img src="{{victim.photo}}" style="max-width:200px; max-height:200px"><br>
<form action="/" method="get">
<input type="hidden" name="action" value="kill"><br>
{% if is_inactive(victim) %}
<span data-toggle="popover" data-trigger="hover" data-container="body" title="Выдержка из правил:" data-content="<p>2.6.1. Если за срок более 7 дней участник не совершает ни одного убийства, он получает статус — &laquo;неактивный&raquo;.</p><p>2.6.2. Жертву со статусом &laquo;неактивный&raquo; можно убить, не выполняя условия 2.4.5 (становится невозможным аппелирование к правилу 2.7)</p><p>2.4.5. Нельзя убивать при свидетелях - будь то участник игры или посторонний человек. </p><p>2.7. Если возникла спорная ситуация по поводу убийства, жертва должна привести свидетеля, который видел убийство.</p>" class="label label-success">
Неактивный
</span><br><br>
{% endif %}
Введите {% if victim.sex == '1' %}её{% else %}его{% endif %} пароль сюда:<br>
<input type="input" class="form-control" name="password" style="width:200px; margin-top:10px"><br>
<input type="submit" class="btn btn-default" value="Проверить">
</form>
</div>
</div>
{% endfor %}
<div class="col-md-4"></div>
</div>
<div style="height: 40px"></div>
{% endif %}
{% if game_status == 'game-started' or game_status == 'game-finished' %}
<div>
У вас очков:
<h1 style="color:red"><b>{{ killed | length }} + {{additional_points}}</b></h1><br>
</div>
<div style="height: 40px"></div>
{% endif %}
<!--
{% if killed != [] %}
<div style="height:100px"></div>
<div style="height: 50px">
Вы убили человек: {{ killed | length }}<br>
</div>
{% for user in killed %}
<a href="http://vk.com/id{{user.uid}}"><div style="width: 150px; height:150px; text-align: center; display:inline-block">
{% if user.photo_rec %}
<img src="{{ user.photo_rec }}" style="max-width:50px; max-height:50px"><br>
{% else %}
<img src="{{ user.photo }}" style="max-width:50px; max-height:50px"><br>
{% endif %}
{{user.first_name}}<br>{{user.last_name}}
</div></a>
{% endfor %}
{% endif %}
{% if has_cards_of != [] %}
<div style="height: 50px">
У вас есть карточек: {{ has_cards_of | length }}<br>
</div>
{% endif %}
{% for user in has_cards_of %}
<a href="http://vk.com/id{{user.uid}}"><div style="width: 150px; height:150px; text-align: center; display:inline-block">
{% if user.photo_rec %}
<img src="{{ user.photo_rec }}" style="max-width:50px; max-height:50px"><br>
{% else %}
<img src="{{ user.photo }}" style="max-width:50px; max-height:50px"><br>
{% endif %}
{{user.first_name}}<br>{{user.last_name}}
</div></a>
{% endfor %}
-->
{% endif %}
{% if user.enabled and not user.alive and (game_status == 'game-started' or game_status == 'game-finished') %}
К сожалению вы были убиты пользователем <a href="http://vk.com/id{{user.killed_by}}">{{killed_by.first_name}} {{killed_by.last_name}}</a>.<br>
{% if killed_by.sex == '1' %}Она ввела{% else %}Он ввел{% endif %} ваш пароль: {{user.password}}
<div style="height:50px"></div>
У вас было очков:
<h1 style="color:red"><b>{{ killed | length}} + {{additional_points}}</b></h1>
<div style="height:20px"></div>
<!--
{% if has_cards_of != [] %}
<div style="height: 50px">
У вас было карточек: {{ has_cards_of | length }}<br>
</div>
{% endif %}
{% for user in has_cards_of %}
<a href="http://vk.com/id{{user.uid}}"><div style="width: 150px; height:150px; text-align: center; display:inline-block">
{% if user.photo_rec %}
<img src="{{ user.photo_rec }}" style="max-width:50px; max-height:50px"><br>
{% else %}
<img src="{{ user.photo }}" style="max-width:50px; max-height:50px"><br>
{% endif %}
{{user.first_name}}<br>{{user.last_name}}
</div></a>
{% endfor %}
-->
{% endif %}
{% if not user.enabled %}
<h1>{{user.first_name}} {{user.last_name}}</h1><br>
{% if disabled_users_message %}
{% autoescape false %}
{{disabled_users_message}}
<br><br>
{% endautoescape %}
{% endif %}
{% autoescape false %}
{{user.message}}<br><br>
{% endautoescape %}
{% if user.photo %}
<img src="{{user.photo}}" style="max-width:200px"><br><br>
{% else %}
<i><span style="color:gray">Нет большого фото</span></i><br><br>
{% endif %}
<button class="btn btn-default btn-xs" data-toggle="modal" data-target="#myModal">
Указать другую фотографию
</button>
<div style="height:25px"></div>
<button type="button" id="show-password" class="btn btn-primary">
Показать пароль
</button><br>
<div style="height:40px"></div>
{% endif %}
{% if game_status == 'game-started' or game_status == 'game-finished' %}
<div>
Количества очков у участников:
<script>
var scores = {{score_list}};
var res = []
var found = false
for(var i in scores){
res[i] = scores[i]
if(!found && scores[i] == {{killed | length}} + {{additional_points}}){
res[i] = '<span style="color:red;"><b>' + scores[i] + '</b></span>'
found = true
}
}
document.write('<h3>' + res.join(' &nbsp; ') + '</h3>')
</script>
</div>
<div style="height:40px"></div>
<div class="row">
<div class="col-xs-4">
Всего участников:<br>
<h1>{{num_of_enabled_users}}</h1>
</div>
<div class="col-xs-4">
Игра длится дней:<br>
<h1>{{game_lasts_days}}</h1>
</div>
<div class="col-xs-4">
Из них осталось в живых:<br>
<h1>{{num_of_alive_users}}</h1>
</div>
</div>
{% endif %}
<!--- <div id="event-mess"> <span id="timetoevent"></span></div> -->
<br><br>
<div style="height:40px"></div>
</center>
</div>
<div style="position:fixed;bottom:0;height:40px;text-valign:top;padding-top:10px;width:100%;text-align:center;background:white; border-top: 1px solid gray">
<!-- Число участников: {{num_of_users}}<br> -->
Администраторы: <a href="http://vk.com/id26769197">Дмитрий Марков</a>, <a href="http://vk.com/id170556210">Бамбр Намжавин</a>, <a href="http://vk.com/id1330405">Элен Теванян</a>. Программирование: <a href="http://vk.com/pallada92">Ярослав Сергиенко</a>
</div>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<form action="/" method="get">
<input type="hidden" name="action" value="set_picture">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Закрыть</span></button>
<h4 class="modal-title" id="myModalLabel">Указать фотографию</h4>
</div>
<div class="modal-body">
<p>
<input class="form-control" name="photo_url" value="{% if user.photo %}{{user.photo}}{% endif %}" placeholder="Введите URL изображения">
<br>Рекомендуемый размер: 200 пикселей.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Отмена</button>
<input type="submit" class="btn btn-primary" value="Отправить">
</div>
</div>
</form>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script>
var show_pas = true;
$('#show-password').click(function () {
var btn = $(this)
if(show_pas){
btn.text('{{user.password}}');
}else{
btn.text('Показать пароль');
}
btn.button('toggle')
show_pas = !show_pas;
});
$(function () { $("[data-toggle='popover']").popover({ html : true }); });
</script>
</body>
</html>
{% endautoescape %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment