aboutsummaryrefslogtreecommitdiff
path: root/src/db.js
blob: f1d41fc8302ab021a35a94022f8523ebe83d0928 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { join, dirname, resolve } from 'path'
import { Low, JSONFile } from 'lowdb'
import { fileURLToPath } from 'url'
import crypto from 'crypto'

const __dirname = dirname(fileURLToPath(import.meta.url))
const file = join(__dirname, '../data', 'db.json')
let adapter
let db

const init = async () => {
    adapter = new JSONFile(file)
    db = new Low(adapter)

    await db.read()
    db.data ||= { rooms: {} }
    await db.write()
}

const read = async () => {
    await db.read()
    return db.data
}

const write = async (obj) => {
    await db.read()
    let roomHash

    switch (obj.type) {
        case 'introduction':
        case 'expense':
            roomHash = _getHash(obj.roomId)
            db.data.rooms[roomHash] ||= { events: [] }
            db.data.rooms[roomHash].events.push(obj)
            break

        default:
            throw new Error('Invalid type for db.write()')
            break
    }

    await db.write()
}

const undo = async (roomId) => {
    const roomHash = _getHash(roomId)
    await db.read()

    db.data.rooms[roomHash] ||= { events: [] }

    db.data.rooms[roomHash].events.pop()

    await db.write()
}

const reset = async (roomId) => {
    const roomHash = _getHash(roomId)
    await db.read()

    db.data.rooms[roomHash] ||= { events: [] }

    db.data.rooms[roomHash].events = db.data.rooms[roomHash].events.filter(
        (e) => {
            return !(e.type === 'expense' || e.type === 'transaction')
        }
    )

    await db.write()
}

const fullreset = async (roomId) => {
    const roomHash = _getHash(roomId)
    await db.read()

    db.data.rooms[roomHash] ||= { events: [] }

    delete db.data.rooms[roomHash]

    await db.write()
}

const getUsers = async (roomId) => {
    const roomHash = _getHash(roomId)
    const data = await read()

    let userIds = []

    data.rooms[roomHash] ||= { events: [] }

    data.rooms[roomHash].events.forEach((event) => {
        if (event.type === 'introduction') {
            userIds.push(event.userId)
        }
    })

    return userIds
}

const getEventLog = async (roomId, limit) => {
    const roomHash = _getHash(roomId)
    const data = await read()

    data.rooms[roomHash] ||= { events: [] }

    return data.rooms[roomHash].events.slice(-(limit || 4))
}

const getBalance = async (roomId) => {
    const roomHash = _getHash(roomId)
    const data = await read()

    let balance = {
        userIds: [],
    }
    
    data.rooms[roomHash] ||= { events: [] }

    data.rooms[roomHash].events.forEach((event) => {
        switch (event.type) {
            case 'introduction':
                balance.userIds.push(event.userId)
                balance[event.userId] = {
                    totalSpent: 0,
                    spentForUserId: {},
                }
                break

            case 'expense':
                balance[event.userId].totalSpent += event.data.amount
                balance.userIds.forEach((userId) => {
                    balance[event.userId].spentForUserId[userId] ||= 0
                    balance[event.userId].spentForUserId[userId] +=
                        event.data.amount / balance.userIds.length
                })
                break

            default:
                break
        }
    })

    return balance
}

const _getHash = (string) => {
    return crypto.createHash('sha256').update(string, 'utf8').digest('hex')
}

export default {
    init: init,
    read: read,
    write: write,
    undo: undo,
    reset: reset,
    fullreset: fullreset,
    getUsers: getUsers,
    getEventLog: getEventLog,
    getBalance: getBalance,
}