| @@ -4,6 +4,7 @@ import math | |||||
| import os | import os | ||||
| import random | import random | ||||
| import sys | import sys | ||||
| import wave | |||||
| from datetime import datetime, timedelta | from datetime import datetime, timedelta | ||||
| from enum import Enum, auto | from enum import Enum, auto | ||||
| from typing import Callable, TypedDict | from typing import Callable, TypedDict | ||||
| @@ -24,10 +25,12 @@ from pygame.time import Clock | |||||
| from pytchat.core.pytchat import PytchatCore | from pytchat.core.pytchat import PytchatCore | ||||
| from pytchat.processors.default.processor import Chat | from pytchat.processors.default.processor import Chat | ||||
| from aques import Aques | |||||
| from common_module import CommonModule | from common_module import CommonModule | ||||
| from nizika_ai.config import DB | from nizika_ai.config import DB | ||||
| from nizika_ai.consts import (AnswerType, Character, GPTModel, Platform, | |||||
| QueryType) | |||||
| from nizika_ai.models import Answer, AnsweredFlag, Query, User | from nizika_ai.models import Answer, AnsweredFlag, Query, User | ||||
| from nizika_ai.consts import AnswerType, Character, GPTModel, Platform, QueryType | |||||
| pygame.init () | pygame.init () | ||||
| @@ -42,12 +45,11 @@ def main ( | |||||
| ) -> None: | ) -> None: | ||||
| game = Game () | game = Game () | ||||
| Bg (game) | Bg (game) | ||||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||||
| balloon = Balloon (game) | balloon = Balloon (game) | ||||
| deerjika = Deerjika (game, DeerjikaPattern.RELAXED, | |||||
| x = CWindow.WIDTH * 3 / 4, | |||||
| y = CWindow.HEIGHT - 120, | |||||
| balloon = balloon) | |||||
| CurrentTime (game, SYSTEM_FONT) | CurrentTime (game, SYSTEM_FONT) | ||||
| broadcast = Broadcast (os.environ['BROADCAST_CODE']) | broadcast = Broadcast (os.environ['BROADCAST_CODE']) | ||||
| try: | try: | ||||
| @@ -60,6 +62,7 @@ def main ( | |||||
| pygame.quit () | pygame.quit () | ||||
| sys.exit () | sys.exit () | ||||
| if not balloon.enabled: | if not balloon.enabled: | ||||
| DB.begin_transaction () | |||||
| answer_flags = (AnsweredFlag.where ('platform', Platform.YOUTUBE.value) | answer_flags = (AnsweredFlag.where ('platform', Platform.YOUTUBE.value) | ||||
| .where ('answered', False) | .where ('answered', False) | ||||
| .get ()) | .get ()) | ||||
| @@ -68,9 +71,10 @@ def main ( | |||||
| answer = Answer.find (answer_flag.answer_id) | answer = Answer.find (answer_flag.answer_id) | ||||
| if answer.answer_type == AnswerType.YOUTUBE_REPLY.value: | if answer.answer_type == AnswerType.YOUTUBE_REPLY.value: | ||||
| query = Query.find (answer.query_id) | query = Query.find (answer.query_id) | ||||
| balloon.talk (query.content, answer.content) | |||||
| deerjika.talk (query.content, answer.content) | |||||
| answer_flag.answered = True | answer_flag.answered = True | ||||
| answer_flag.save () | answer_flag.save () | ||||
| DB.commit () | |||||
| add_query (broadcast) | add_query (broadcast) | ||||
| game.redraw () | game.redraw () | ||||
| @@ -297,7 +301,16 @@ class BgGrass (GameObject): | |||||
| super ().redraw () | super ().redraw () | ||||
| class Deerjika (GameObject): | |||||
| class Creature (GameObject): | |||||
| sound: Sound | |||||
| def bell ( | |||||
| self, | |||||
| ) -> None: | |||||
| self.sound.play () | |||||
| class Deerjika (Creature): | |||||
| """ | """ | ||||
| 伊地知ニジカ | 伊地知ニジカ | ||||
| @@ -309,9 +322,12 @@ class Deerjika (GameObject): | |||||
| """ | """ | ||||
| height: int | height: int | ||||
| scale: float = .8 | |||||
| scale: float = .8 | |||||
| surfaces: list[Surface] | surfaces: list[Surface] | ||||
| width: int | width: int | ||||
| talking: bool = False | |||||
| wav: bytearray | None = None | |||||
| balloon: Balloon | |||||
| def __init__ ( | def __init__ ( | ||||
| self, | self, | ||||
| @@ -321,10 +337,14 @@ class Deerjika (GameObject): | |||||
| layer: int | None = None, | layer: int | None = None, | ||||
| x: float = 0, | x: float = 0, | ||||
| y: float = 0, | y: float = 0, | ||||
| balloon: Balloon | None = None, | |||||
| ): | ): | ||||
| if balloon is None: | |||||
| raise Exception | |||||
| super ().__init__ (game, layer, x = x, y = y) | super ().__init__ (game, layer, x = x, y = y) | ||||
| self.pattern = pattern | self.pattern = pattern | ||||
| self.direction = direction | self.direction = direction | ||||
| self.balloon = balloon | |||||
| match pattern: | match pattern: | ||||
| case DeerjikaPattern.NORMAL: | case DeerjikaPattern.NORMAL: | ||||
| ... | ... | ||||
| @@ -340,6 +360,7 @@ class Deerjika (GameObject): | |||||
| surface.subsurface (x, 0, self.width, self.height)) | surface.subsurface (x, 0, self.width, self.height)) | ||||
| case Direction.RIGHT: | case Direction.RIGHT: | ||||
| ... | ... | ||||
| self.sound = Sound ('assets/noon.wav') | |||||
| def redraw ( | def redraw ( | ||||
| self, | self, | ||||
| @@ -348,9 +369,44 @@ class Deerjika (GameObject): | |||||
| (self.width * self.scale, self.height * self.scale)) | (self.width * self.scale, self.height * self.scale)) | ||||
| self.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y))) | self.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y))) | ||||
| super ().redraw () | super ().redraw () | ||||
| self.x = random.randrange (CWindow.WIDTH) | |||||
| self.y = random.randrange (CWindow.HEIGHT) | |||||
| self.arg = math.radians (random.randrange (360)) | |||||
| if (not self.balloon.enabled) and self.talking: | |||||
| self.talking = False | |||||
| if (self.balloon.enabled and self.balloon.frame >= FPS * 3 | |||||
| and not self.talking): | |||||
| self.read_out () | |||||
| def talk ( | |||||
| self, | |||||
| query: str, | |||||
| answer: str, | |||||
| ) -> None: | |||||
| self.bell () | |||||
| self._create_wav (answer) | |||||
| length = 300 | |||||
| if self.wav is not None: | |||||
| with wave.open ('./nizika_talking.wav', 'rb') as f: | |||||
| length = int (FPS * (f.getnframes () / f.getframerate () + 4)) | |||||
| self.balloon.talk (query, answer, length = length) | |||||
| def read_out ( | |||||
| self, | |||||
| ) -> None: | |||||
| Sound ('./nizika_talking.wav').play () | |||||
| self.talking = True | |||||
| def _create_wav ( | |||||
| self, | |||||
| message: str, | |||||
| ) -> None: | |||||
| try: | |||||
| self.wav = Aques.main (message, False) | |||||
| except: | |||||
| self.wav = None | |||||
| if self.wav is None: | |||||
| return | |||||
| with open ('./nizika_talking.wav', 'wb') as f: | |||||
| f.write (self.wav) | |||||
| class CurrentTime (GameObject): | class CurrentTime (GameObject): | ||||