Starchik1 commited on
Commit
43f0655
·
verified ·
1 Parent(s): ab02f81

Upload 11 files

Browse files
app.py CHANGED
@@ -32,7 +32,93 @@ typing_texts = [
32
  "Хороший наборщик текста может печатать, не глядя на клавиатуру.",
33
  "Скорость набора измеряется в количестве слов в минуту.",
34
  "Точность набора так же важна, как и скорость.",
35
- "Регулярные тренировки помогут вам улучшить навыки набора текста."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  ]
37
 
38
  # Комнаты для многопользовательской игры
@@ -67,9 +153,21 @@ def save_result():
67
  wpm = data.get('wpm', 0)
68
  accuracy = data.get('accuracy', 0)
69
 
70
- result = GameResult(username=username, wpm=wpm, accuracy=accuracy)
71
- db.session.add(result)
72
- db.session.commit()
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  return jsonify({'success': True})
75
 
@@ -102,6 +200,25 @@ def on_join(data):
102
  print(f"Игрок {username} присоединился к комнате {room}")
103
  print(f"Текущие игроки в комнате: {rooms[room]['players'].keys()}")
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  @socketio.on('start_game')
106
  def on_start_game(data):
107
  room = data['room']
 
32
  "Хороший наборщик текста может печатать, не глядя на клавиатуру.",
33
  "Скорость набора измеряется в количестве слов в минуту.",
34
  "Точность набора так же важна, как и скорость.",
35
+ "Регулярные тренировки помогут вам улучшить навыки набора текста.",
36
+ "Все счастливые семьи похожи друг на друга, каждая несчастливая семья несчастлива по-своему. Все смешалось в доме Облонских.",
37
+ "Мой дядя самых честных правил, когда не в шутку занемог, он уважать себя заставил и лучше выдумать не мог.",
38
+ "В начале было Слово, и Слово было у Бога, и Слово было Бог. Оно было в начале у Бога. Все чрез Него начало быть, и без Него ничто не начало быть, что начало быть.",
39
+ "Двадцать лет назад никто не слыхал о капитане Немо, а теперь все знают, что он существует. Точно так же и я, профессор Пьер Аронакс, единственный спутник капитана Немо, расскажу вам то, что до сих пор было скрыто.",
40
+ "Над всем этим возвышался громадный замок с высокими башнями, с длинными флюгерами, развевающимися по ветру. Он был окружен глубоким рвом с водой, в которой плавали дикие лебеди и росли красивейшие тростники.",
41
+ "Человек, который смеется, не всегда смеется от радости. Иногда он смеется от горя, от отчаяния, от ненависти. Смех бывает разный.",
42
+ "Все мы родом из детства. Но не все помнят об этом. Взрослые забывают, что когда-то были детьми. А я помню.",
43
+ "Мы все глядим в Наполеоны; двуногих тварей миллионы для нас орудие одно; нам чувство дико и смешно.",
44
+ "Я памятник себе воздвиг нерукотворный, к нему не зарастет народная тропа, вознесся выше он главою непокорной Александрийского столпа.",
45
+ "Тот, кто не помнит своего прошлого, обречен на то, чтобы пережить его вновь. История учит лишь тому, что она никогда ничему не научила народы.",
46
+ "Мой дом - моя крепость. Но даже крепость можно взять штурмом, если найти в ней слабое место. Поэтому я всегда начеку.",
47
+ "Время - самая большая ценность, которая у нас есть. Его нельзя вернуть, его нельзя накопить, его можно только потратить. И от того, как мы его тратим, зависит наша жизнь.",
48
+ "Книги - корабли мысли, странствующие по волнам времени и бережно несущие свой драгоценный груз от поколения к поколению.",
49
+ "Жизнь - это то, что с тобой происходит, пока ты строишь планы на будущее. Не откладывай на завтра то, что можно сделать сегодня.",
50
+ "Утро туманное, утро седое, нивы печальные, снегом покрытые. Нехотя вспомнишь и время былое, вспомнишь и лица, давно позабытые.",
51
+ "Я пришел к тебе с приветом, рассказать, что солнце встало, что оно горячим светом по листам затрепетало.",
52
+ "Мороз и солнце; день чудесный! Еще ты дремлешь, друг прелестный - пора, красавица, проснись: открой сомкнуты негой взоры навстречу северной Авроры, звездою севера явись!",
53
+ "Белеет парус одинокий в тумане моря голубом. Что ищет о�� в стране далекой? Что кинул он в краю родном?",
54
+ "Люблю грозу в начале мая, когда весенний, первый гром, как бы резвяся и играя, грохочет в небе голубом.",
55
+ "Однажды в студеную зимнюю пору я из лесу вышел; был сильный мороз. Гляжу, поднимается медленно в гору лошадка, везущая хворосту воз.",
56
+ "Ночь, улица, фонарь, аптека, бессмысленный и тусклый свет. Живи еще хоть четверть века - все будет так. Исхода нет.",
57
+ "Я вас любил: любовь еще, быть может, в душе моей угасла не совсем; но пусть она вас больше не тревожит; я не хочу печалить вас ничем.",
58
+ "Я помню чудное мгновенье: передо мной явилась ты, как мимолетное виденье, как гений чистой красоты.",
59
+ "Мой первый друг, мой друг бесценный! И я судьбу благословил, когда мой двор уединенный, печальным снегом занесенный, твой колокольчик огласил.",
60
+
61
+ # Дополнительные фрагменты из русской классической литературы
62
+ "Герой нашего времени, милостивые государи мои, точно портрет, но не одного человека: это портрет, составленный из пороков всего нашего поколения, в полном их развитии.",
63
+ "Чичиков подъехал к дому, который был ни мал, ни велик, но опрятен и прочен. Две русские избы, перенесенные сюда бревно в бревно, заменили флигеля.",
64
+ "Тарас Бульба остановился перед крыльцом и увидел жену свою, которая только что успела его обнять, как уже вскрикнула, вглядываясь в него пристально.",
65
+ "Старик Хоттабыч сидел на диване, поджав под себя ноги, и с упоением читал какую-то толстую книгу. Он был в своем любимом белом костюме и красной феске.",
66
+ "Вечера на хуторе близ Диканьки. Как упоителен, как роскошен летний день в Малороссии! Как томительно жарки те часы, когда полдень блещет в тишине и зное!",
67
+ "Капитанская дочка. Отец мой Андрей Петрович Гринев в молодости своей служил при графе Минихе и вышел в отставку премьер-майором в 17.. году.",
68
+ "Война и мир. Ну, князь, Генуя и Лукка стали не больше, как поместьями фамилии Бонапарте. Нет, я вам вперед говорю, если вы мне не скажете, что у нас война, если вы еще позволите себе защищать все гадости, все ужасы этого антихриста (право, я верю, что он антихрист), — я вас больше не знаю, вы уж не друг мой, вы уж не мой верный раб, как вы говорите.",
69
+ "Преступление и наказание. В начале июля, в чрезвычайно жаркое время, под вечер, один молодой человек вышел из своей каморки, которую нанимал от жильцов в С-м переулке, на улицу и медленно, как бы в нерешимости, отправился к К-ну мосту.",
70
+ "Идиот. В конце ноября, в оттепель, часов в девять утра, поезд Петербургско-Варшавской железной дороги на всех парах подходил к Петербургу. Было так сыро и туманно, что насилу рассвело.",
71
+ "Мастер и Маргарита. Однажды весною, в час небывало жаркого заката, в Москве, на Патриарших прудах, появились два гражданина. Первый из них, одетый в летнюю серенькую пару, был маленького роста, упитан, лыс, свою приличную шляпу пирожком нес в руке, а на хорошо выбритом лице его помещались сверхъестественных размеров очки в черной роговой оправе.",
72
+ "Собачье сердце. На обоях золотые корзины, букеты роз, над ними вьются голубые птички. На высоком узком камине прислонен к стене кремовый пастушок. Перед камином на стеклянном столике лежат раскрытая громадная книга с пестрыми картинками и мертвая птица с распущенным хвостом.",
73
+ "Тихий Дон. Мелеховский двор - на самом краю хутора. Воротца со скотиньего база ведут на север к Дону. Крутой восьмисаженный спуск меж замшелых в прозелени меловых глыб, и вот берег: перламутровая россыпь ракушек, серая изломистая кайма нацелованной волнами гальки и дальше - перекипающее под ветром вороненой рябью стремя Дона.",
74
+ "Обломов. В Гороховой улице, в одном из больших домов, народонаселения которого стало бы на целый уездный город, лежал утром в постели, на своей квартире, Илья Ильич Обломов.",
75
+ "Отцы и дети. - Что, Петр, не видать еще? - спрашивал 20 мая 1859 года, выходя без шапки на низкое крылечко постоялого двора на *** шоссе, барин лет сорока с небольшим, в запыленном пальто и клетчатых панталонах, у своего слуги, молодого и щекастого малого с беловатым пухом на подбородке и маленькими тусклыми глазенками.",
76
+ "Анна Каренина. Степан Аркадьич Облонский - Стива, как его звали в свете, - проснулся в обычный час, то есть в восемь часов утра, не в спальне жены, а в своем кабинете, на сафьянном диване.",
77
+ "Евгений Онегин. Мой брат двоюродный, Буянов, в пуху, в картузе с козырьком (Как вам, конечно, он знаком), явился; мой поэт, Буянов мне друг и родственник.",
78
+ "Горе от ума. Чацкий. Ну вот и день прошел, и с ним все призраки, весь чад и дым надежд, насмешливых речей, невыполнимых планов, загадок и сомнений... Какое-то волненье в крови, а голове пустота.",
79
+ "Вишневый сад. Любовь Андреевна. Детская, милая моя, прекрасная комната... Я тут спала, когда была маленькой... И вот я как маленькая... А я родилась здесь, тут прошло мое детство, моя юность.",
80
+ "Ревизор. Городничий. Я пригласил вас, господа, с тем, чтобы сообщить вам пренеприятное известие: к нам едет ревизор.",
81
+ "Мертвые души. Чичиков. Эх, русский народец! Не любит умирать своею смертью!",
82
+
83
+ # Фрагменты из зарубежной литературы
84
+ "Гамлет. Быть или не быть - вот в чем вопрос. Достойно ль смиряться под ударами судьбы, иль надо оказать сопротивленье и в смертной схватке с целым морем бед покончить с ними?",
85
+ "Ромео и Джульетта. Но мягче свет! Что за краса в окне? То свет зари, и солнце - Джульетта! Встань, ясная заря, убей луну-завистницу: она и без того больна и зелена от горя, что ты ее прекрасней во сто крат.",
86
+ "Дон Кихот. В некоем селе Ламанчском, которого название у меня нет охоты припоминать, не так давно жил-был один из тех идальго, чье имущество заключается в фамильном копье, древнем щите, тощей кляче и борзой собаке.",
87
+ "Три мушкетера. В первый понедельник апреля 1625 года все население городка Менга, где некогда родился автор «Романа о розе», казалось взволнованным так, словно гугеноты собирались превратить его во вторую Ла-Рошель.",
88
+ "Граф Монте-Кристо. 24 февраля 1815 года дозорный Нотр-Дам де-ла-Гард дал знать о приближении трехмачтового корабля «Фараон», идущего из Смирны, Триеста и Неаполя.",
89
+ "Гордость и предубеждение. Все знают, что молодой человек, располагающий средствами, должен подыскивать себе жену.",
90
+ "Джейн Эйр. В тот день нельзя было и думать о прогулке. Правда, утром мы еще бродили часок по дорожкам облетевшего сада, но после обеда холодный зимний ветер нагнал угрюмые тучи и полил такой пронизывающий дождь, что и речи не могло быть ни о какой попытке выйти еще раз.",
91
+ "Портрет Дориана Грея. Густой аромат роз наполнял мастерскую художника, а когда в саду поднимался летний ветерок, он, влетая в открытую дверь, приносил с собой то пьянящий запах сирени, то нежное благоухание алых цветов шиповника.",
92
+ "Алиса в Стране чудес. Алисе наскучило сидеть с сестрой без дела на берегу реки; разок-другой она заглянула в книжку, которую читала сестра, но там не было ни картинок, ни разговоров. «Что толку в книжке, – подумала Алиса, – если в ней нет ни картинок, ни разговоров?»",
93
+ "Маленький принц. Когда мне было шесть лет, в книге под названием «Правдивые истории», где рассказывалось про девственные леса, я увидел однажды удивительную картинку.",
94
+ "Властелин колец. Когда господин Бильбо Бэггинс из Бэг-Энда объявил, что скоро отпразднует свое стоодиннадцатилетие весьма пышным угощением, весь Хоббитон загудел и заволновался.",
95
+ "Гарри Поттер и философский камень. Мистер и миссис Дурсль проживали в доме номер четыре по Тисовой улице и всегда с гордостью заявляли, что они, слава богу, абсолютно нормальные люди.",
96
+ "Хоббит, или Туда и обратно. В земле была нора, а в норе жил хоббит. Не мерзкая грязная сырая нора, где со всех сторон торчат хвосты червей и противно пахнет тиной, но и не сухая песчаная голая нора, где не на что сесть и нечего съесть.",
97
+ "Шерлок Холмс. Для Шерлока Холмса она всегда оставалась «той женщиной». Я редко слышал, чтобы он называл ее каким-либо другим именем. В его глазах она затмевала всех представительниц своего пола.",
98
+ "Великий Гэтсби. В юные и ранимые годы отец дал мне совет, который с тех пор не выходит у меня из головы. «Если тебе вдруг захочется осудить кого-то, – сказал он, – вспомни, что не все люди на свете обладают теми преимуществами, которыми обладал ты».",
99
+ "Над пропастью во ржи. Если вам на самом деле хочется услышать эту историю, вы, наверное, прежде всего захотите узнать, где я родился, как провел свое дурацкое детство, что делали мои родители до моего рождения, – словом, всю эту давид-копперфилдовскую муть.",
100
+ "Сто лет одиночества. Много лет спустя, перед самым расстрелом, полковник Аурелиано Буэндиа вспомнит тот далекий день, когда отец повел его поглядеть на лед.",
101
+ "1984. Был холодный ясный апрельский день, и часы пробили тринадцать. Уткнув подбородок в грудь, чтобы спастись от злого ветра, Уинстон Смит торопливо шмыгнул за стеклянную дверь жилого дома «Победа», но все-таки впустил за собой вихрь зернистой пыли.",
102
+ "Преступление и наказание. Раскольников. Я хотел Наполеоном сделаться, оттого и убил... Вошь ли я, как все, или человек? Смогу ли я переступить или не смогу?",
103
+ "Мастер и Маргарита. Рукописи не горят.",
104
+
105
+ # Современные тексты
106
+ "Метро 2033. Артём. Станция казалась обреченной. Еще немного - и она погибнет, ее жители будут убиты, а те, кому повезет умереть сразу, избегнут страшной участи оказаться пищей для мутантов.",
107
+ "Ночной дозор. Иные не умирают насовсем. Мы уходим в сумрак и становимся его частью.",
108
+ "Географ глобус пропил. Служкин сидел на подоконнике в школьном коридоре и курил, опасливо поглядывая на двери учительской.",
109
+ "Generation П. Вавилен Татарский. Когда-то в России и правда жило беспечальное юное поколение, которое улыбнулось лету, морю и солнцу – и выбрало «Пепси».",
110
+ "Лавр. Евгений Водолазкин. Прежде Лавр был Арсением. Когда он родился, никто не предполагал, что впоследствии его назовут Устином, Амвросием и, наконец, Лавром.",
111
+ "Текст. Глеб Янковский. Телефон – это вообще единственное, что у человека по-настоящему личное. Раньше, может, это была душа, но теперь – телефон.",
112
+ "Зулейха открывает глаза. Зулейха открывает глаза. Темно, как в погребе. Сонно вздыхают за тонкой занавеской гуси. Месяц скоро народится, а пока стоят самые темные ночи.",
113
+ "Теория бесконечности. Мы все живем в мире, где каждый день происходят миллионы событий, и каждое из них может изменить нашу жизнь навсегда.",
114
+ "Цифровая крепость. Сьюзан Флетчер бросила быстрый взгляд на ТРАНСТЕКСТ. Она всегда думала, что шифры весьма, весьма сложны. Но ведь для обычных пользователей они не должны быть сложнее обычных слов.",
115
+ "Код да Винчи. Роберт Лэнгдон. Знаменитый куратор Лувра Жак Соньер был найден мертвым в Большой галерее музея. Рядом с телом полиция обнаружила загадочное послание.",
116
+ "Облачный атлас. Тихоокеанский дневник Адама Юинга. Четверг, 7 ноября. За бортом Пропеллер, судна капитана Моллинью, показался остров Чатем.",
117
+ "Бойцовский клуб. Тайлер Дёрден. Первое правило Бойцовского клуба: никому не рассказывать о Бойцовском клубе. Второе правило Бойцовского клуба: никогда никому не рассказывать о Бойцовском клубе.",
118
+ "Голодные игры. Китнисс Эвердин. Когда я просыпаюсь, другая половина кровати уже остыла. Я протягиваю руку, ищу тепло Прим, но нахожу лишь грубую холщовую обивку матраса.",
119
+ "Дивергент. Беатрис Прайор. В нашем доме есть только одно зеркало, и оно спрятано за раздвижной панелью во втором этаже коридора. Наша фракция позволяет смотреться в него р��з в три месяца.",
120
+ "Марсианин. Марк Уотни. Я в полной заднице. Вот моя обдуманная оценка ситуации: я в полной заднице.",
121
+ "Игра престолов. Эддард Старк. Зима близко."
122
  ]
123
 
124
  # Комнаты для многопользовательской игры
 
153
  wpm = data.get('wpm', 0)
154
  accuracy = data.get('accuracy', 0)
155
 
156
+ # Проверяем, есть ли уже результат с таким именем пользователя
157
+ existing_result = GameResult.query.filter_by(username=username).first()
158
+
159
+ # Если результат существует и новый результат лучше, обновляем его
160
+ if existing_result:
161
+ if wpm > existing_result.wpm:
162
+ existing_result.wpm = wpm
163
+ existing_result.accuracy = accuracy
164
+ existing_result.date = datetime.utcnow()
165
+ db.session.commit()
166
+ else:
167
+ # Если результата нет, создаем новый
168
+ result = GameResult(username=username, wpm=wpm, accuracy=accuracy)
169
+ db.session.add(result)
170
+ db.session.commit()
171
 
172
  return jsonify({'success': True})
173
 
 
200
  print(f"Игрок {username} присоединился к комнате {room}")
201
  print(f"Текущие игроки в комнате: {rooms[room]['players'].keys()}")
202
 
203
+ @socketio.on('player_ready')
204
+ def on_player_ready(data):
205
+ room = data['room']
206
+ if room in rooms:
207
+ # Отмечаем игрока как готового
208
+ rooms[room]['players'][request.sid]['ready'] = True
209
+
210
+ # Проверяем, все ли игроки готовы
211
+ all_ready = True
212
+ for player_id in rooms[room]['players']:
213
+ if not rooms[room]['players'][player_id].get('ready', False):
214
+ all_ready = False
215
+ break
216
+
217
+ # Если все готовы, начинаем обратный отсчет
218
+ if all_ready and len(rooms[room]['players']) > 0:
219
+ emit('countdown_start', {}, to=room)
220
+ print(f"Все игроки в комнате {room} готовы. Начинаем обратный отсчет.")
221
+
222
  @socketio.on('start_game')
223
  def on_start_game(data):
224
  room = data['room']
instance/typing_game.db CHANGED
Binary files a/instance/typing_game.db and b/instance/typing_game.db differ
 
static/css/style.css CHANGED
@@ -435,6 +435,10 @@ main {
435
  color: var(--text-color);
436
  }
437
 
 
 
 
 
438
  .player-progress {
439
  width: 60%;
440
  height: 20px;
@@ -456,6 +460,35 @@ main {
456
  gap: 15px;
457
  }
458
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
459
  .leaderboard-container {
460
  background-color: var(--secondary-color);
461
  border-radius: 10px;
 
435
  color: var(--text-color);
436
  }
437
 
438
+ .player-ready {
439
+ color: var(--success-color);
440
+ }
441
+
442
  .player-progress {
443
  width: 60%;
444
  height: 20px;
 
460
  gap: 15px;
461
  }
462
 
463
+ /* Стили для кнопки готовности */
464
+ .ready {
465
+ background-color: var(--success-color);
466
+ color: var(--light-text);
467
+ }
468
+
469
+ /* Стили для обратного отсчёта */
470
+ .countdown {
471
+ display: none;
472
+ position: absolute;
473
+ top: 50%;
474
+ left: 50%;
475
+ transform: translate(-50%, -50%);
476
+ font-size: 5rem;
477
+ color: var(--text-color);
478
+ z-index: 100;
479
+ text-shadow: 0 0 10px rgba(233, 69, 96, 0.7);
480
+ }
481
+
482
+ .pulse {
483
+ animation: pulse 1s ease-in-out;
484
+ }
485
+
486
+ @keyframes pulse {
487
+ 0% { transform: translate(-50%, -50%) scale(0.8); opacity: 0.7; }
488
+ 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 1; }
489
+ 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.7; }
490
+ }
491
+
492
  .leaderboard-container {
493
  background-color: var(--secondary-color);
494
  border-radius: 10px;
static/js/game.js CHANGED
@@ -56,6 +56,45 @@ document.addEventListener('DOMContentLoaded', function() {
56
  function startGame() {
57
  if (gameActive) return;
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  fetchText();
60
  inputArea.value = '';
61
  inputArea.disabled = false;
@@ -76,6 +115,9 @@ document.addEventListener('DOMContentLoaded', function() {
76
  resultContainer.style.display = 'none';
77
  overseer.classList.remove('show');
78
 
 
 
 
79
  // Обновляем статистику
80
  updateStats();
81
  }
 
56
  function startGame() {
57
  if (gameActive) return;
58
 
59
+ // Скрываем кнопку старта во время обратного отсчёта
60
+ startBtn.disabled = true;
61
+
62
+ // Запускаем обратный отсчёт
63
+ startCountdown();
64
+ }
65
+
66
+ // Функция обратного отсчёта
67
+ function startCountdown() {
68
+ const countdown = document.getElementById('countdown');
69
+ countdown.style.display = 'block';
70
+ let count = 3;
71
+
72
+ countdown.textContent = count;
73
+ countdown.classList.add('pulse');
74
+
75
+ const countdownTimer = setInterval(() => {
76
+ count--;
77
+
78
+ if (count > 0) {
79
+ countdown.textContent = count;
80
+ countdown.classList.remove('pulse');
81
+ void countdown.offsetWidth; // Перезапуск анимации
82
+ countdown.classList.add('pulse');
83
+ } else if (count === 0) {
84
+ countdown.textContent = 'Старт!';
85
+ countdown.classList.remove('pulse');
86
+ void countdown.offsetWidth;
87
+ countdown.classList.add('pulse');
88
+ } else {
89
+ clearInterval(countdownTimer);
90
+ countdown.style.display = 'none';
91
+ initializeGame();
92
+ }
93
+ }, 1000);
94
+ }
95
+
96
+ // Инициализация игры после обратного отсчёта
97
+ function initializeGame() {
98
  fetchText();
99
  inputArea.value = '';
100
  inputArea.disabled = false;
 
115
  resultContainer.style.display = 'none';
116
  overseer.classList.remove('show');
117
 
118
+ // Разблокируем кнопку старта
119
+ startBtn.disabled = false;
120
+
121
  // Обновляем статистику
122
  updateStats();
123
  }
static/js/multiplayer.js CHANGED
@@ -4,11 +4,12 @@ document.addEventListener('DOMContentLoaded', function() {
4
  const usernameInput = document.getElementById('username');
5
  const roomInput = document.getElementById('room');
6
  const joinBtn = document.getElementById('joinBtn');
7
- const startBtn = document.getElementById('startBtn');
8
  const gameContainer = document.getElementById('gameContainer');
9
  const textDisplay = document.getElementById('textDisplay');
10
  const inputArea = document.getElementById('inputArea');
11
  const playersList = document.getElementById('playersList');
 
12
 
13
  // Переменные для игры
14
  let socket;
@@ -20,6 +21,7 @@ document.addEventListener('DOMContentLoaded', function() {
20
  let mistakes = 0;
21
  let totalChars = 0;
22
  let gameActive = false;
 
23
 
24
  // Инициализация Socket.IO
25
  function initSocket() {
@@ -37,14 +39,11 @@ document.addEventListener('DOMContentLoaded', function() {
37
  if (data.started && !gameActive) {
38
  startGame(data.text);
39
  }
40
-
41
- // Активируем кнопку старта только для первого игрока
42
- const playerIds = Object.keys(data.players);
43
- if (playerIds.length > 0 && playerIds[0] === socket.id) {
44
- startBtn.disabled = false;
45
- } else {
46
- startBtn.disabled = true;
47
- }
48
  });
49
 
50
  socket.on('game_started', (data) => {
@@ -108,6 +107,12 @@ document.addEventListener('DOMContentLoaded', function() {
108
  playerName.className = 'player-name';
109
  playerName.textContent = player.username;
110
 
 
 
 
 
 
 
111
  const playerProgress = document.createElement('div');
112
  playerProgress.className = 'player-progress';
113
 
@@ -149,6 +154,25 @@ document.addEventListener('DOMContentLoaded', function() {
149
  }
150
  }
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  // Начало игры
153
  function startGame(textContent) {
154
  text = textContent;
@@ -265,10 +289,16 @@ document.addEventListener('DOMContentLoaded', function() {
265
  joinRoom();
266
  });
267
 
268
- startBtn.addEventListener('click', function() {
269
- socket.emit('start_game', {
270
- room: room
271
- });
 
 
 
 
 
 
272
  });
273
 
274
  // Инициализация
 
4
  const usernameInput = document.getElementById('username');
5
  const roomInput = document.getElementById('room');
6
  const joinBtn = document.getElementById('joinBtn');
7
+ const readyBtn = document.getElementById('readyBtn');
8
  const gameContainer = document.getElementById('gameContainer');
9
  const textDisplay = document.getElementById('textDisplay');
10
  const inputArea = document.getElementById('inputArea');
11
  const playersList = document.getElementById('playersList');
12
+ const countdown = document.getElementById('countdown');
13
 
14
  // Переменные для игры
15
  let socket;
 
21
  let mistakes = 0;
22
  let totalChars = 0;
23
  let gameActive = false;
24
+ let playerReady = false;
25
 
26
  // Инициализация Socket.IO
27
  function initSocket() {
 
39
  if (data.started && !gameActive) {
40
  startGame(data.text);
41
  }
42
+ });
43
+
44
+ socket.on('countdown_start', () => {
45
+ // Начинаем обратный отсчет
46
+ startCountdown();
 
 
 
47
  });
48
 
49
  socket.on('game_started', (data) => {
 
107
  playerName.className = 'player-name';
108
  playerName.textContent = player.username;
109
 
110
+ // Добавляем индикатор готовности
111
+ if (player.ready) {
112
+ playerName.textContent += ' ✓';
113
+ playerName.classList.add('player-ready');
114
+ }
115
+
116
  const playerProgress = document.createElement('div');
117
  playerProgress.className = 'player-progress';
118
 
 
154
  }
155
  }
156
 
157
+ // Обратный отсчет перед началом игры
158
+ function startCountdown() {
159
+ readyBtn.disabled = true;
160
+ countdown.style.display = 'block';
161
+ let count = 3;
162
+ countdown.textContent = count;
163
+
164
+ const countdownInterval = setInterval(() => {
165
+ count--;
166
+ countdown.textContent = count;
167
+
168
+ if (count <= 0) {
169
+ clearInterval(countdownInterval);
170
+ countdown.style.display = 'none';
171
+ socket.emit('start_game', { room: room });
172
+ }
173
+ }, 1000);
174
+ }
175
+
176
  // Начало игры
177
  function startGame(textContent) {
178
  text = textContent;
 
289
  joinRoom();
290
  });
291
 
292
+ readyBtn.addEventListener('click', function() {
293
+ if (!playerReady) {
294
+ playerReady = true;
295
+ readyBtn.textContent = 'Готов!';
296
+ readyBtn.classList.add('ready');
297
+
298
+ socket.emit('player_ready', {
299
+ room: room
300
+ });
301
+ }
302
  });
303
 
304
  // Инициализация
templates/game.html CHANGED
@@ -39,6 +39,8 @@
39
  <button id="startBtn" class="btn btn-primary">Начать игру</button>
40
  </div>
41
 
 
 
42
  <div class="result-container" id="resultContainer">
43
  <h2>Результаты</h2>
44
  <div class="result-details">
 
39
  <button id="startBtn" class="btn btn-primary">Начать игру</button>
40
  </div>
41
 
42
+ <div class="countdown" id="countdown"></div>
43
+
44
  <div class="result-container" id="resultContainer">
45
  <h2>Результаты</h2>
46
  <div class="result-details">
templates/multiplayer.html CHANGED
@@ -22,7 +22,8 @@
22
  </div>
23
 
24
  <div class="controls">
25
- <button id="startBtn" class="btn btn-primary" disabled>Начать игру</button>
 
26
  </div>
27
 
28
  <div class="players-list" id="playersList">
 
22
  </div>
23
 
24
  <div class="controls">
25
+ <button id="readyBtn" class="btn btn-primary" готов!</button>
26
+ <div id="countdown" class="countdown" style="display: none;">3</div>
27
  </div>
28
 
29
  <div class="players-list" id="playersList">