chore(release): 0.2.0
[risinglegends.git] / src / server / map.ts
1 import { City, Location, Path } from "../shared/map";
2 import type { Player } from '../shared/player';
3 import type { Travel } from '../shared/travel';
4 import { db } from './lib/db';
5 import { random } from 'lodash';
6
7 export async function getAllServices(city_id: number): Promise<Location[]> {
8   return db.select('*')
9             .from<Location>('locations')
10             .where({city_id})
11             .orderBy('type')
12             .orderBy('display_order');
13 }
14
15 export async function getService(serverId: number): Promise<Location> {
16   return db.select('*').first().from<Location>('locations').where({
17     id: serverId
18   });
19 }
20
21 export async function getAllPaths(city_id: number): Promise<Path[]> {
22   const res = await db.raw(`
23                 select 
24                   paths.*, c1.name as starting_city_name, c2.name as ending_city_name
25                 from paths
26                 join cities c1 on c1.id = paths.starting_city 
27                 join cities c2 on c2.id = paths.ending_city
28                 where paths.starting_city = ?
29                 `, [city_id]);
30
31   return res.rows.map(row => {
32     return {
33       starting_city: row.starting_city,
34       ending_city: row.ending_city,
35       starting_city_name: row.starting_city_name,
36       ending_city_name: row.ending_city_name
37     }
38   });
39 }
40
41 export async function getCityDetails(city_id: number): Promise<City> {
42   return db.first().select('*').from<City>('cities').where({id: city_id});
43 }
44
45 export async function travel(player: Player, dest_id: number): Promise<Travel> {
46   const city = await getCityDetails(dest_id);
47   const path = await db.first().select('*').from('paths').where({
48     starting_city: player.city_id,
49     ending_city: dest_id
50   });
51   if(!city) {
52     throw new Error('Invalid destination city');
53   }
54   if(!path) {
55     throw new Error(`Invalid path ${player.city_id} => ${dest_id}`);
56   }
57
58   const deviation = Math.floor(path.distance * (random(3,10)/100));
59   const steps = random(path.distance - deviation, path.distance + deviation);
60
61   const rows = await db('travel').insert({
62     player_id: player.id,
63     source_id: player.city_id,
64     destination_id: dest_id,
65     total_distance: steps
66   }).returning('*');
67
68   if(rows.length !== 1) {
69     console.log(rows);
70     throw new Error('Unexpected response when creating travel');
71   }
72
73   return rows[0] as Travel;
74 }
75
76 export async function stepForward(player_id: string): Promise<Travel> {
77   const rows = await db('travel').increment('current_position').returning('*');
78
79   if(rows.length !== 1) {
80     console.log(rows);
81     throw new Error('Unexpected response when moving');
82   }
83
84   return rows[0] as Travel;
85 }
86
87 export async function clearTravelPlan(player_id: string): Promise<Travel> {
88   return completeTravel(player_id);
89 }
90
91 export async function completeTravel(player_id: string): Promise<Travel> {
92   const rows = await db('travel').where({player_id}).delete().returning('*');
93   if(rows.length !== 1) {
94     console.log(rows);
95     throw new Error('Unexpected response when moving');
96   }
97
98   return rows[0] as Travel;
99 }
100
101 export async function getTravelPlan(player_id: string): Promise<Travel> {
102   return db.select('*').first().from<Travel>('travel').where({
103     player_id
104   });
105 }