exploring/fighting is functional
[sketchy-heroes.git] / src / routes / move.ts
index 8ba79f0f32ab46b8ea81837ec0351a6b6a28d13f..b57dd5e931c1f95b8f0e7a786c9bb913bae242b3 100644 (file)
@@ -3,7 +3,15 @@ import { Static, Type } from '@sinclair/typebox';
 import { prisma } from '../lib/db';
 import { ForbiddenError } from '../lib/http-errors';
 import { random, sample } from 'lodash';
-import {Biome, Player} from '@prisma/client';
+import {Biome, Player, Fight} from '@prisma/client';
+import {now} from '../lib/time';
+import {generateMonster} from '../services/generate-monster';
+
+type RawMonsterSelection = {
+  monsterId: string;
+  biome: Biome,
+  time: {min: number, max:number}[]
+}
 
 const MoveInput = Type.Object({
   params: Type.Object({
@@ -19,7 +27,8 @@ export type MoveOutputType = {
     id: string;
     biome: Biome
   },
-  displayText: string
+  displayText: string,
+  generatedMonster: Fight | null
 }
 
 const moveStatements = [
@@ -34,6 +43,8 @@ export const move = server.post<MoveInputType, MoveOutputType>('/v1/accounts/:pl
   authenicated: true
 }, async req => {
 
+  let generatedMonster: Fight | null = null;
+
   const player = await prisma.player.findUnique({
     where: {
       id: req.params.playerId
@@ -86,12 +97,74 @@ export const move = server.post<MoveInputType, MoveOutputType>('/v1/accounts/:pl
     }
   });
 
+
+  // now that you have moved, you have 40% chance of fighting a monster
+  if(random(0, 100) < 20) {
+    // ok it's battle time!
+    // retrieve all monsters from the database that are in this biome
+    // that are within the timeframe specified!
+    const monsters = await prisma.$queryRaw`
+    WITH p AS ( -- probability
+               SELECT *,
+               weight::NUMERIC / sum(weight) OVER () AS probability
+               FROM "MonsterBiome"
+               WHERE biome = ${player.zoneBiome.biome}
+              ),
+              cp AS ( -- cumulative probability
+                     SELECT *,
+                     sum(p.probability) OVER (
+                       ORDER BY probability DESC
+                       ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+                     ) AS cumprobability
+                     FROM p
+                    ),
+              fp AS (
+                  SELECT
+        cp.*,
+        cp.cumprobability - cp.probability AS startprobability,
+        cp.cumprobability AS endprobability
+    FROM cp
+              )
+
+                    SELECT "monsterId", biome, time FROM fp
+WHERE random() BETWEEN startprobability AND endprobability;
+    ` as RawMonsterSelection[];
+
+    // now lets filter out the timezones!
+    const moment = now();
+    const availableMonsters = monsters.filter(monster => {
+      return monster.time.filter(time => {
+        return time.min <= moment && time.max >= moment;
+      });
+    })
+
+    if(availableMonsters) {
+      const selectedMonster = sample(availableMonsters);
+      if(selectedMonster) {
+        const monster = await prisma.monster.findUnique({
+          where: {
+            id: selectedMonster.monsterId
+          }
+        });
+
+        if(monster) {
+          generatedMonster = await prisma.fight.create({
+            data: generateMonster(player, monster)
+          });
+        }
+      }
+    }
+
+  }
+
+
   return {
     player,
     biome: {
-      id: player.zoneBiome.id,
+      id: player.zoneBiomeId,
       biome: player.zoneBiome.biome
     },
+    generatedMonster,
     displayText: sample(moveStatements) || moveStatements[0]
-  }
+  };
 });