|
|
from flask import Flask, render_template, request, jsonify, session |
|
|
from flask_socketio import SocketIO, emit, join_room, leave_room |
|
|
import os |
|
|
import random |
|
|
import json |
|
|
from datetime import datetime |
|
|
from flask_sqlalchemy import SQLAlchemy |
|
|
|
|
|
app = Flask(__name__) |
|
|
app.config['SECRET_KEY'] = os.urandom(24) |
|
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///typing_game.db' |
|
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
|
|
socketio = SocketIO(app) |
|
|
db = SQLAlchemy(app) |
|
|
|
|
|
|
|
|
class GameResult(db.Model): |
|
|
id = db.Column(db.Integer, primary_key=True) |
|
|
username = db.Column(db.String(50), nullable=False) |
|
|
wpm = db.Column(db.Float, nullable=False) |
|
|
accuracy = db.Column(db.Float, nullable=False) |
|
|
date = db.Column(db.DateTime, default=datetime.utcnow) |
|
|
|
|
|
|
|
|
with app.app_context(): |
|
|
db.create_all() |
|
|
|
|
|
|
|
|
typing_texts = [ |
|
|
"Быстрый набор текста - это навык, который может значительно повысить вашу продуктивность.", |
|
|
"Практика ежедневного набора текста поможет вам стать быстрее и точнее.", |
|
|
"Хороший наборщик текста может печатать, не глядя на клавиатуру.", |
|
|
"Скорость набора измеряется в количестве слов в минуту.", |
|
|
"Точность набора так же важна, как и скорость.", |
|
|
"Регулярные тренировки помогут вам улучшить навыки набора текста.", |
|
|
"Все счастливые семьи похожи друг на друга, каждая несчастливая семья несчастлива по-своему. Все смешалось в доме Облонских.", |
|
|
"Мой дядя самых честных правил, когда не в шутку занемог, он уважать себя заставил и лучше выдумать не мог.", |
|
|
"В начале было Слово, и Слово было у Бога, и Слово было Бог. Оно было в начале у Бога. Все чрез Него начало быть, и без Него ничто не начало быть, что начало быть.", |
|
|
"Двадцать лет назад никто не слыхал о капитане Немо, а теперь все знают, что он существует. Точно так же и я, профессор Пьер Аронакс, единственный спутник капитана Немо, расскажу вам то, что до сих пор было скрыто.", |
|
|
"Над всем этим возвышался громадный замок с высокими башнями, с длинными флюгерами, развевающимися по ветру. Он был окружен глубоким рвом с водой, в которой плавали дикие лебеди и росли красивейшие тростники.", |
|
|
"Человек, который смеется, не всегда смеется от радости. Иногда он смеется от горя, от отчаяния, от ненависти. Смех бывает разный.", |
|
|
"Все мы родом из детства. Но не все помнят об этом. Взрослые забывают, что когда-то были детьми. А я помню.", |
|
|
"Мы все глядим в Наполеоны; двуногих тварей миллионы для нас орудие одно; нам чувство дико и смешно.", |
|
|
"Я памятник себе воздвиг нерукотворный, к нему не зарастет народная тропа, вознесся выше он главою непокорной Александрийского столпа.", |
|
|
"Тот, кто не помнит своего прошлого, обречен на то, чтобы пережить его вновь. История учит лишь тому, что она никогда ничему не научила народы.", |
|
|
"Мой дом - моя крепость. Но даже крепость можно взять штурмом, если найти в ней слабое место. Поэтому я всегда начеку.", |
|
|
"Время - самая большая ценность, которая у нас есть. Его нельзя вернуть, его нельзя накопить, его можно только потратить. И от того, как мы его тратим, зависит наша жизнь.", |
|
|
"Книги - корабли мысли, странствующие по волнам времени и бережно несущие свой драгоценный груз от поколения к поколению.", |
|
|
"Жизнь - это то, что с тобой происходит, пока ты строишь планы на будущее. Не откладывай на завтра то, что можно сделать сегодня.", |
|
|
"Утро туманное, утро седое, нивы печальные, снегом покрытые. Нехотя вспомнишь и время былое, вспомнишь и лица, давно позабытые.", |
|
|
"Я пришел к тебе с приветом, рассказать, что солнце встало, что оно горячим светом по листам затрепетало.", |
|
|
"Мороз и солнце; день чудесный! Еще ты дремлешь, друг прелестный - пора, красавица, проснись: открой сомкнуты негой взоры навстречу северной Авроры, звездою севера явись!", |
|
|
"Белеет парус одинокий в тумане моря голубом. Что ищет он в стране далекой? Что кинул он в краю родном?", |
|
|
"Люблю грозу в начале мая, когда весенний, первый гром, как бы резвяся и играя, грохочет в небе голубом.", |
|
|
"Однажды в студеную зимнюю пору я из лесу вышел; был сильный мороз. Гляжу, поднимается медленно в гору лошадка, везущая хворосту воз.", |
|
|
"Ночь, улица, фонарь, аптека, бессмысленный и тусклый свет. Живи еще хоть четверть века - все будет так. Исхода нет.", |
|
|
"Я вас любил: любовь еще, быть может, в душе моей угасла не совсем; но пусть она вас больше не тревожит; я не хочу печалить вас ничем.", |
|
|
"Я помню чудное мгновенье: передо мной явилась ты, как мимолетное виденье, как гений чистой красоты.", |
|
|
"Мой первый друг, мой друг бесценный! И я судьбу благословил, когда мой двор уединенный, печальным снегом занесенный, твой колокольчик огласил.", |
|
|
|
|
|
|
|
|
"Герой нашего времени, милостивые государи мои, точно портрет, но не одного человека: это портрет, составленный из пороков всего нашего поколения, в полном их развитии.", |
|
|
"Чичиков подъехал к дому, который был ни мал, ни велик, но опрятен и прочен. Две русские избы, перенесенные сюда бревно в бревно, заменили флигеля.", |
|
|
"Тарас Бульба остановился перед крыльцом и увидел жену свою, которая только что успела его обнять, как уже вскрикнула, вглядываясь в него пристально.", |
|
|
"Старик Хоттабыч сидел на диване, поджав под себя ноги, и с упоением читал какую-то толстую книгу. Он был в своем любимом белом костюме и красной феске.", |
|
|
"Вечера на хуторе близ Диканьки. Как упоителен, как роскошен летний день в Малороссии! Как томительно жарки те часы, когда полдень блещет в тишине и зное!", |
|
|
"Капитанская дочка. Отец мой Андрей Петрович Гринев в молодости своей служил при графе Минихе и вышел в отставку премьер-майором в 17.. году.", |
|
|
"Война и мир. Ну, князь, Генуя и Лукка стали не больше, как поместьями фамилии Бонапарте. Нет, я вам вперед говорю, если вы мне не скажете, что у нас война, если вы еще позволите себе защищать все гадости, все ужасы этого антихриста (право, я верю, что он антихрист), — я вас больше не знаю, вы уж не друг мой, вы уж не мой верный раб, как вы говорите.", |
|
|
"Преступление и наказание. В начале июля, в чрезвычайно жаркое время, под вечер, один молодой человек вышел из своей каморки, которую нанимал от жильцов в С-м переулке, на улицу и медленно, как бы в нерешимости, отправился к К-ну мосту.", |
|
|
"Идиот. В конце ноября, в оттепель, часов в девять утра, поезд Петербургско-Варшавской железной дороги на всех парах подходил к Петербургу. Было так сыро и туманно, что насилу рассвело.", |
|
|
"Мастер и Маргарита. Однажды весною, в час небывало жаркого заката, в Москве, на Патриарших прудах, появились два гражданина. Первый из них, одетый в летнюю серенькую пару, был маленького роста, упитан, лыс, свою приличную шляпу пирожком нес в руке, а на хорошо выбритом лице его помещались сверхъестественных размеров очки в черной роговой оправе.", |
|
|
"Собачье сердце. На обоях золотые корзины, букеты роз, над ними вьются голубые птички. На высоком узком камине прислонен к стене кремовый пастушок. Перед камином на стеклянном столике лежат раскрытая громадная книга с пестрыми картинками и мертвая птица с распущенным хвостом.", |
|
|
"Тихий Дон. Мелеховский двор - на самом краю хутора. Воротца со скотиньего база ведут на север к Дону. Крутой восьмисаженный спуск меж замшелых в прозелени меловых глыб, и вот берег: перламутровая россыпь ракушек, серая изломистая кайма нацелованной волнами гальки и дальше - перекипающее под ветром вороненой рябью стремя Дона.", |
|
|
"Обломов. В Гороховой улице, в одном из больших домов, народонаселения которого стало бы на целый уездный город, лежал утром в постели, на своей квартире, Илья Ильич Обломов.", |
|
|
"Отцы и дети. - Что, Петр, не видать еще? - спрашивал 20 мая 1859 года, выходя без шапки на низкое крылечко постоялого двора на *** шоссе, барин лет сорока с небольшим, в запыленном пальто и клетчатых панталонах, у своего слуги, молодого и щекастого малого с беловатым пухом на подбородке и маленькими тусклыми глазенками.", |
|
|
"Анна Каренина. Степан Аркадьич Облонский - Стива, как его звали в свете, - проснулся в обычный час, то есть в восемь часов утра, не в спальне жены, а в своем кабинете, на сафьянном диване.", |
|
|
"Евгений Онегин. Мой брат двоюродный, Буянов, в пуху, в картузе с козырьком (Как вам, конечно, он знаком), явился; мой поэт, Буянов мне друг и родственник.", |
|
|
"Горе от ума. Чацкий. Ну вот и день прошел, и с ним все призраки, весь чад и дым надежд, насмешливых речей, невыполнимых планов, загадок и сомнений... Какое-то волненье в крови, а голове пустота.", |
|
|
"Вишневый сад. Любовь Андреевна. Детская, милая моя, прекрасная комната... Я тут спала, когда была маленькой... И вот я как маленькая... А я родилась здесь, тут прошло мое детство, моя юность.", |
|
|
"Ревизор. Городничий. Я пригласил вас, господа, с тем, чтобы сообщить вам пренеприятное известие: к нам едет ревизор.", |
|
|
"Мертвые души. Чичиков. Эх, русский народец! Не любит умирать своею смертью!", |
|
|
|
|
|
|
|
|
"Гамлет. Быть или не быть - вот в чем вопрос. Достойно ль смиряться под ударами судьбы, иль надо оказать сопротивленье и в смертной схватке с целым морем бед покончить с ними?", |
|
|
"Ромео и Джульетта. Но мягче свет! Что за краса в окне? То свет зари, и солнце - Джульетта! Встань, ясная заря, убей луну-завистницу: она и без того больна и зелена от горя, что ты ее прекрасней во сто крат.", |
|
|
"Дон Кихот. В некоем селе Ламанчском, которого название у меня нет охоты припоминать, не так давно жил-был один из тех идальго, чье имущество заключается в фамильном копье, древнем щите, тощей кляче и борзой собаке.", |
|
|
"Три мушкетера. В первый понедельник апреля 1625 года все население городка Менга, где некогда родился автор «Романа о розе», казалось взволнованным так, словно гугеноты собирались превратить его во вторую Ла-Рошель.", |
|
|
"Граф Монте-Кристо. 24 февраля 1815 года дозорный Нотр-Дам де-ла-Гард дал знать о приближении трехмачтового корабля «Фараон», идущего из Смирны, Триеста и Неаполя.", |
|
|
"Гордость и предубеждение. Все знают, что молодой человек, располагающий средствами, должен подыскивать себе жену.", |
|
|
"Джейн Эйр. В тот день нельзя было и думать о прогулке. Правда, утром мы еще бродили часок по дорожкам облетевшего сада, но после обеда холодный зимний ветер нагнал угрюмые тучи и полил такой пронизывающий дождь, что и речи не могло быть ни о какой попытке выйти еще раз.", |
|
|
"Портрет Дориана Грея. Густой аромат роз наполнял мастерскую художника, а когда в саду поднимался летний ветерок, он, влетая в открытую дверь, приносил с собой то пьянящий запах сирени, то нежное благоухание алых цветов шиповника.", |
|
|
"Алиса в Стране чудес. Алисе наскучило сидеть с сестрой без дела на берегу реки; разок-другой она заглянула в книжку, которую читала сестра, но там не было ни картинок, ни разговоров. «Что толку в книжке, – подумала Алиса, – если в ней нет ни картинок, ни разговоров?»", |
|
|
"Маленький принц. Когда мне было шесть лет, в книге под названием «Правдивые истории», где рассказывалось про девственные леса, я увидел однажды удивительную картинку.", |
|
|
"Властелин колец. Когда господин Бильбо Бэггинс из Бэг-Энда объявил, что скоро отпразднует свое стоодиннадцатилетие весьма пышным угощением, весь Хоббитон загудел и заволновался.", |
|
|
"Гарри Поттер и философский камень. Мистер и миссис Дурсль проживали в доме номер четыре по Тисовой улице и всегда с гордостью заявляли, что они, слава богу, абсолютно нормальные люди.", |
|
|
"Хоббит, или Туда и обратно. В земле была нора, а в норе жил хоббит. Не мерзкая грязная сырая нора, где со всех сторон торчат хвосты червей и противно пахнет тиной, но и не сухая песчаная голая нора, где не на что сесть и нечего съесть.", |
|
|
"Шерлок Холмс. Для Шерлока Холмса она всегда оставалась «той женщиной». Я редко слышал, чтобы он называл ее каким-либо другим именем. В его глазах она затмевала всех представительниц своего пола.", |
|
|
"Великий Гэтсби. В юные и ранимые годы отец дал мне совет, который с тех пор не выходит у меня из головы. «Если тебе вдруг захочется осудить кого-то, – сказал он, – вспомни, что не все люди на свете обладают теми преимуществами, которыми обладал ты».", |
|
|
"Над пропастью во ржи. Если вам на самом деле хочется услышать эту историю, вы, наверное, прежде всего захотите узнать, где я родился, как провел свое дурацкое детство, что делали мои родители до моего рождения, – словом, всю эту давид-копперфилдовскую муть.", |
|
|
"Сто лет одиночества. Много лет спустя, перед самым расстрелом, полковник Аурелиано Буэндиа вспомнит тот далекий день, когда отец повел его поглядеть на лед.", |
|
|
"1984. Был холодный ясный апрельский день, и часы пробили тринадцать. Уткнув подбородок в грудь, чтобы спастись от злого ветра, Уинстон Смит торопливо шмыгнул за стеклянную дверь жилого дома «Победа», но все-таки впустил за собой вихрь зернистой пыли.", |
|
|
"Преступление и наказание. Раскольников. Я хотел Наполеоном сделаться, оттого и убил... Вошь ли я, как все, или человек? Смогу ли я переступить или не смогу?", |
|
|
"Мастер и Маргарита. Рукописи не горят.", |
|
|
|
|
|
|
|
|
"Метро 2033. Артём. Станция казалась обреченной. Еще немного - и она погибнет, ее жители будут убиты, а те, кому повезет умереть сразу, избегнут страшной участи оказаться пищей для мутантов.", |
|
|
"Ночной дозор. Иные не умирают насовсем. Мы уходим в сумрак и становимся его частью.", |
|
|
"Географ глобус пропил. Служкин сидел на подоконнике в школьном коридоре и курил, опасливо поглядывая на двери учительской.", |
|
|
"Generation П. Вавилен Татарский. Когда-то в России и правда жило беспечальное юное поколение, которое улыбнулось лету, морю и солнцу – и выбрало «Пепси».", |
|
|
"Лавр. Евгений Водолазкин. Прежде Лавр был Арсением. Когда он родился, никто не предполагал, что впоследствии его назовут Устином, Амвросием и, наконец, Лавром.", |
|
|
"Текст. Глеб Янковский. Телефон – это вообще единственное, что у человека по-настоящему личное. Раньше, может, это была душа, но теперь – телефон.", |
|
|
"Зулейха открывает глаза. Зулейха открывает глаза. Темно, как в погребе. Сонно вздыхают за тонкой занавеской гуси. Месяц скоро народится, а пока стоят самые темные ночи.", |
|
|
"Теория бесконечности. Мы все живем в мире, где каждый день происходят миллионы событий, и каждое из них может изменить нашу жизнь навсегда.", |
|
|
"Цифровая крепость. Сьюзан Флетчер бросила быстрый взгляд на ТРАНСТЕКСТ. Она всегда думала, что шифры весьма, весьма сложны. Но ведь для обычных пользователей они не должны быть сложнее обычных слов.", |
|
|
"Код да Винчи. Роберт Лэнгдон. Знаменитый куратор Лувра Жак Соньер был найден мертвым в Большой галерее музея. Рядом с телом полиция обнаружила загадочное послание.", |
|
|
"Облачный атлас. Тихоокеанский дневник Адама Юинга. Четверг, 7 ноября. За бортом Пропеллер, судна капитана Моллинью, показался остров Чатем.", |
|
|
"Бойцовский клуб. Тайлер Дёрден. Первое правило Бойцовского клуба: никому не рассказывать о Бойцовском клубе. Второе правило Бойцовского клуба: никогда никому не рассказывать о Бойцовском клубе.", |
|
|
"Голодные игры. Китнисс Эвердин. Когда я просыпаюсь, другая половина кровати уже остыла. Я протягиваю руку, ищу тепло Прим, но нахожу лишь грубую холщовую обивку матраса.", |
|
|
"Дивергент. Беатрис Прайор. В нашем доме есть только одно зеркало, и оно спрятано за раздвижной панелью во втором этаже коридора. Наша фракция позволяет смотреться в него раз в три месяца.", |
|
|
"Марсианин. Марк Уотни. Я в полной заднице. Вот моя обдуманная оценка ситуации: я в полной заднице.", |
|
|
"Игра престолов. Эддард Старк. Зима близко." |
|
|
] |
|
|
|
|
|
|
|
|
rooms = {} |
|
|
|
|
|
@app.route('/') |
|
|
def index(): |
|
|
return render_template('index.html') |
|
|
|
|
|
@app.route('/game') |
|
|
def game(): |
|
|
return render_template('game.html') |
|
|
|
|
|
@app.route('/multiplayer') |
|
|
def multiplayer(): |
|
|
return render_template('multiplayer.html') |
|
|
|
|
|
@app.route('/leaderboard') |
|
|
def leaderboard(): |
|
|
results = GameResult.query.order_by(GameResult.wpm.desc()).limit(10).all() |
|
|
return render_template('leaderboard.html', results=results) |
|
|
|
|
|
@app.route('/get_text', methods=['GET']) |
|
|
def get_text(): |
|
|
text = random.choice(typing_texts) |
|
|
return jsonify({'text': text}) |
|
|
|
|
|
@app.route('/save_result', methods=['POST']) |
|
|
def save_result(): |
|
|
data = request.json |
|
|
username = data.get('username', 'Anonymous') |
|
|
wpm = data.get('wpm', 0) |
|
|
accuracy = data.get('accuracy', 0) |
|
|
|
|
|
|
|
|
existing_result = GameResult.query.filter_by(username=username).first() |
|
|
|
|
|
|
|
|
if existing_result: |
|
|
if wpm > existing_result.wpm: |
|
|
existing_result.wpm = wpm |
|
|
existing_result.accuracy = accuracy |
|
|
existing_result.date = datetime.utcnow() |
|
|
db.session.commit() |
|
|
else: |
|
|
|
|
|
result = GameResult(username=username, wpm=wpm, accuracy=accuracy) |
|
|
db.session.add(result) |
|
|
db.session.commit() |
|
|
|
|
|
return jsonify({'success': True}) |
|
|
|
|
|
|
|
|
@socketio.on('join') |
|
|
def on_join(data): |
|
|
username = data['username'] |
|
|
room = data['room'] |
|
|
join_room(room) |
|
|
|
|
|
if room not in rooms: |
|
|
rooms[room] = { |
|
|
'players': {}, |
|
|
'text': random.choice(typing_texts), |
|
|
'started': False |
|
|
} |
|
|
|
|
|
rooms[room]['players'][request.sid] = { |
|
|
'username': username, |
|
|
'progress': 0, |
|
|
'wpm': 0, |
|
|
'accuracy': 0, |
|
|
'finished': False |
|
|
} |
|
|
|
|
|
|
|
|
emit('room_update', rooms[room], to=room) |
|
|
|
|
|
|
|
|
print(f"Игрок {username} присоединился к комнате {room}") |
|
|
print(f"Текущие игроки в комнате: {rooms[room]['players'].keys()}") |
|
|
|
|
|
@socketio.on('player_ready') |
|
|
def on_player_ready(data): |
|
|
room = data['room'] |
|
|
if room in rooms: |
|
|
|
|
|
rooms[room]['players'][request.sid]['ready'] = True |
|
|
|
|
|
|
|
|
all_ready = True |
|
|
for player_id in rooms[room]['players']: |
|
|
if not rooms[room]['players'][player_id].get('ready', False): |
|
|
all_ready = False |
|
|
break |
|
|
|
|
|
|
|
|
if all_ready and len(rooms[room]['players']) > 0: |
|
|
emit('countdown_start', {}, to=room) |
|
|
print(f"Все игроки в комнате {room} готовы. Начинаем обратный отсчет.") |
|
|
|
|
|
@socketio.on('start_game') |
|
|
def on_start_game(data): |
|
|
room = data['room'] |
|
|
if room in rooms: |
|
|
rooms[room]['started'] = True |
|
|
emit('game_started', {'text': rooms[room]['text']}, to=room) |
|
|
print(f"Игра в комнате {room} началась. Текст: {rooms[room]['text'][:20]}...") |
|
|
|
|
|
@socketio.on('update_progress') |
|
|
def on_update_progress(data): |
|
|
room = data['room'] |
|
|
progress = data['progress'] |
|
|
wpm = data['wpm'] |
|
|
accuracy = data['accuracy'] |
|
|
|
|
|
if room in rooms and request.sid in rooms[room]['players']: |
|
|
rooms[room]['players'][request.sid]['progress'] = progress |
|
|
rooms[room]['players'][request.sid]['wpm'] = wpm |
|
|
rooms[room]['players'][request.sid]['accuracy'] = accuracy |
|
|
|
|
|
if progress >= 100: |
|
|
rooms[room]['players'][request.sid]['finished'] = True |
|
|
|
|
|
emit('progress_update', rooms[room]['players'], to=room) |
|
|
|
|
|
@socketio.on('disconnect') |
|
|
def on_disconnect(): |
|
|
for room_id, room_data in list(rooms.items()): |
|
|
if request.sid in room_data['players']: |
|
|
del room_data['players'][request.sid] |
|
|
leave_room(room_id) |
|
|
|
|
|
if not room_data['players']: |
|
|
del rooms[room_id] |
|
|
else: |
|
|
emit('room_update', room_data, to=room_id) |
|
|
|
|
|
if __name__ == '__main__': |
|
|
socketio.run(app, debug=True) |