Skip to content

Commit bc3dae5

Browse files
authored
Merge pull request #46 from RisingStack/master
feat: feat: move item purchases to different tab + add config options
2 parents 890647f + 4d1da78 commit bc3dae5

14 files changed

+365
-210
lines changed

.ebextensions/https-instance.config

Lines changed: 0 additions & 65 deletions
This file was deleted.

.ebextensions/privatekey.config

Lines changed: 0 additions & 20 deletions
This file was deleted.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ yarn-debug.log*
2424
yarn-error.log*
2525

2626
.npmrc
27+
28+
# for local deployment purposes
29+
/.ebextensions

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,25 @@ Go to the `<host>/migration` page (e.g. (https://cybersim.demcloud.org/migrate)[
162162
- After filling in the relevant Airtable details, click the "Migrate the database" button.
163163

164164
By following these steps, you can successfully migrate data from Airtable to the PostgreSQL database, ensuring that your new game incorporates the customized data you have prepared.
165+
166+
# Airtable Handbook
167+
168+
### PURCHASED MITIGATIONS
169+
170+
In the game, mitigations are organized into groups according to their category. You can customize the order of these mitigations using the following steps:
171+
172+
1. Access the "purchase_mitigations" table.
173+
2. In the toolbar, click on the "Group" option, and then select the "category" field. Airtable will automatically reorganize the mitigations, grouping them just as they appear in the application.
174+
3. Within each category, you can rearrange the mitigations according to your preferences using the drag-and-drop feature. The order you set here will reflect how they appear in the actual game.
175+
176+
### LOCATIONS
177+
178+
Currently, the game exclusively accommodates exactly two locations. You have the flexibility to name these locations as you desire within the "locations" table.
179+
180+
:warning: **Please exercise caution and refrain from modifying the "location_code" fields. Altering the default values ('hq', 'local') here can disrupt the application's functionality!** :warning:
181+
182+
Changing the names of the locations in this section will solely impact how they are displayed in the header menu, tabs, and action titles. Role names (e.g., "HQ IT Team") remain distinct and should be configured separately within the **ROLES** table.
183+
184+
## DICTIONARY
185+
186+
You have the ability to modify the terminology associated with "polls" in this section. For instance, you can replace "poll" or "budget" with alternative words. To introduce a new synonym, simply edit the synonym column as needed.

knexfile.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ module.exports = {
44
client: 'pg',
55
connection: {
66
connectionString: process.env.DB_URL,
7-
ssl: { rejectUnauthorized: false },
7+
ssl:
8+
process.env.NODE_ENV === 'production'
9+
? { rejectUnauthorized: false }
10+
: false,
811
},
912
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
exports.up = async (knex) => {
2+
await knex.schema.createTable('location', (tbl) => {
3+
tbl.string('id').primary().notNullable();
4+
tbl.string('name').notNullable();
5+
tbl.enu('type', ['hq', 'local']).notNullable();
6+
});
7+
};
8+
9+
exports.down = async (knex) => {
10+
await knex.schema.dropTableIfExists('location');
11+
};
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
exports.up = async (knex) => {
2+
// #region GAME_MITIGATION TABLE
3+
const locationExists = await knex.schema.hasColumn(
4+
'game_mitigation',
5+
'location',
6+
);
7+
8+
if (locationExists) {
9+
await knex.schema.alterTable('game_mitigation', (tbl) => {
10+
tbl.dropColumn('location');
11+
});
12+
}
13+
// #endregion
14+
15+
// #region MITIGATION TABLE
16+
/**
17+
* Since 'mitigations' are only connected to injections (events),
18+
* replace 'hq_cost', 'local_cost', 'is_hq' and 'is_local' columns
19+
* with a single 'cost' column.
20+
*/
21+
const hqCostExists = await knex.schema.hasColumn('mitigation', 'hq_cost');
22+
if (hqCostExists) {
23+
await knex.schema.alterTable('mitigation', (tbl) => {
24+
tbl.dropColumn('hq_cost');
25+
});
26+
}
27+
28+
const localCostExists = await knex.schema.hasColumn(
29+
'mitigation',
30+
'local_cost',
31+
);
32+
if (localCostExists) {
33+
await knex.schema.alterTable('mitigation', (tbl) => {
34+
tbl.dropColumn('local_cost');
35+
});
36+
}
37+
38+
const isHqExists = await knex.schema.hasColumn('mitigation', 'is_hq');
39+
if (isHqExists) {
40+
await knex.schema.alterTable('mitigation', (tbl) => {
41+
tbl.dropColumn('is_hq');
42+
});
43+
}
44+
45+
const isLocalExists = await knex.schema.hasColumn('mitigation', 'is_local');
46+
if (isLocalExists) {
47+
await knex.schema.alterTable('mitigation', (tbl) => {
48+
tbl.dropColumn('is_local');
49+
});
50+
}
51+
52+
// Add 'cost' if doesn't exist
53+
const costExists = await knex.schema.hasColumn('mitigation', 'cost');
54+
if (!costExists) {
55+
await knex.schema.alterTable('mitigation', (tbl) => {
56+
tbl.integer('cost');
57+
});
58+
}
59+
// #endregion
60+
61+
// #region RESPONSE TABLE
62+
const responseLocationExists = await knex.schema.hasColumn(
63+
'response',
64+
'location',
65+
);
66+
if (responseLocationExists) {
67+
await knex.schema.alterTable('response', (tbl) => {
68+
tbl.dropColumn('location');
69+
});
70+
}
71+
72+
const responseMitigationTypeExists = await knex.schema.hasColumn(
73+
'response',
74+
'mitigation_type',
75+
);
76+
if (responseMitigationTypeExists) {
77+
await knex.schema.alterTable('response', (tbl) => {
78+
tbl.dropColumn('mitigation_type');
79+
});
80+
}
81+
82+
const responseRequiredMitigationTypeExists = await knex.schema.hasColumn(
83+
'response',
84+
'required_mitigation_type',
85+
);
86+
if (responseRequiredMitigationTypeExists) {
87+
await knex.schema.alterTable('response', (tbl) => {
88+
tbl.dropColumn('required_mitigation_type');
89+
});
90+
}
91+
// #endregion
92+
93+
// #region GAME_LOG
94+
const gameLogMitigationTypeExists = await knex.schema.hasColumn(
95+
'game_log',
96+
'mitigation_type',
97+
);
98+
if (gameLogMitigationTypeExists) {
99+
await knex.schema.alterTable('game_log', (tbl) => {
100+
tbl.dropColumn('mitigation_type');
101+
});
102+
}
103+
// #endregion
104+
};
105+
106+
exports.down = async (knex) => {
107+
// #region GAME_MITIGATION TABLE
108+
const locationExists = await knex.schema.hasColumn(
109+
'game_mitigation',
110+
'location',
111+
);
112+
113+
if (!locationExists) {
114+
await knex.schema.alterTable('game_mitigation', (tbl) => {
115+
tbl.enu('location', ['hq', 'local']).defaultTo('hq').notNullable();
116+
});
117+
}
118+
// #endregion
119+
120+
// #region MITIGATION TABLE
121+
const hqCostExists = await knex.schema.hasColumn('mitigation', 'hq_cost');
122+
if (!hqCostExists) {
123+
await knex.schema.alterTable('mitigation', (tbl) => {
124+
tbl.integer('hq_cost');
125+
});
126+
}
127+
128+
const localCostExists = await knex.schema.hasColumn(
129+
'mitigation',
130+
'local_cost',
131+
);
132+
if (!localCostExists) {
133+
await knex.schema.alterTable('mitigation', (tbl) => {
134+
tbl.integer('local_cost');
135+
});
136+
}
137+
138+
const isHqExists = await knex.schema.hasColumn('mitigation', 'is_hq');
139+
if (!isHqExists) {
140+
await knex.schema.alterTable('mitigation', (tbl) => {
141+
tbl.boolean('is_hq').defaultTo(true).notNullable();
142+
});
143+
}
144+
145+
const isLocalExists = await knex.schema.hasColumn('mitigation', 'is_local');
146+
if (!isLocalExists) {
147+
await knex.schema.alterTable('mitigation', (tbl) => {
148+
tbl.boolean('is_local').defaultTo(false).notNullable();
149+
});
150+
}
151+
152+
// Add 'cost' if doesn't exist
153+
const costExists = await knex.schema.hasColumn('mitigation', 'cost');
154+
if (costExists) {
155+
await knex.schema.alterTable('mitigation', (tbl) => {
156+
tbl.dropColumn('cost');
157+
});
158+
}
159+
// #endregion
160+
161+
// #region RESPONSE TABLE
162+
const responseLocationExists = await knex.schema.hasColumn(
163+
'response',
164+
'location',
165+
);
166+
if (!responseLocationExists) {
167+
await knex.schema.alterTable('response', (tbl) => {
168+
tbl
169+
.enu('location', ['hq', 'local', 'party'])
170+
.defaultTo('hq')
171+
.notNullable();
172+
});
173+
}
174+
175+
const responseMitigationTypeExists = await knex.schema.hasColumn(
176+
'response',
177+
'mitigation_type',
178+
);
179+
if (!responseMitigationTypeExists) {
180+
await knex.schema.alterTable('response', (tbl) => {
181+
tbl.enu('mitigation_type', ['hq', 'local', 'party']);
182+
});
183+
}
184+
185+
const responseRequiredMitigationTypeExists = await knex.schema.hasColumn(
186+
'response',
187+
'required_mitigation_type',
188+
);
189+
if (!responseRequiredMitigationTypeExists) {
190+
await knex.schema.alterTable('response', (tbl) => {
191+
tbl.enu('required_mitigation_type', ['hq', 'local', 'party']);
192+
});
193+
}
194+
// #endregion
195+
196+
// #region GAME_LOG
197+
const gameLogMitigationTypeExists = await knex.schema.hasColumn(
198+
'game_log',
199+
'mitigation_type',
200+
);
201+
if (!gameLogMitigationTypeExists) {
202+
await knex.schema.alterTable('game_log', (tbl) => {
203+
tbl.string('mitigation_type');
204+
});
205+
}
206+
// #endregion
207+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
exports.up = async (knex) => {
2+
await knex.schema.createTable('dictionary', (tbl) => {
3+
tbl.string('id').primary().notNullable();
4+
tbl.string('word').notNullable();
5+
tbl.string('synonym').notNullable();
6+
});
7+
};
8+
9+
exports.down = async (knex) => {
10+
await knex.schema.dropTableIfExists('dictionary');
11+
};

src/app.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ app.get('/mitigations', async (req, res) => {
4545
res.json(records);
4646
});
4747

48+
app.get('/locations', async (req, res) => {
49+
const records = await db('location');
50+
res.json(records);
51+
});
52+
53+
app.get('/dictionary', async (req, res) => {
54+
const records = await db('dictionary').select('word', 'synonym');
55+
res.json(records);
56+
});
57+
4858
app.get('/systems', async (req, res) => {
4959
const records = await db('system');
5060
res.json(records);

0 commit comments

Comments
 (0)