Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Commit

Permalink
add data point to study in postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Sebastian committed Sep 6, 2018
1 parent c794455 commit fd14cbe
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 19 deletions.
4 changes: 2 additions & 2 deletions deployment/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ CREATE TYPE age AS ENUM ('0-14', '15-24', '25-64');
CREATE TYPE mode AS ENUM ('pedestrian', 'bicyclist');
CREATE TYPE posture AS ENUM ('leaning', 'lying', 'sitting', 'sitting on the ground', 'standing');
CREATE TYPE activities AS ENUM ('commerical', 'consuming', 'conversing', 'electronics', 'pets', 'idle', 'running');
CREATE TYPE groups AS ENUM ('1', '2', '3+');
CREATE TYPE objects AS ENUM ('animal', 'bag_carried', 'clothing_cultural', 'clothing_activity', 'goods_carried', 'equipment_construction', 'equipment_receational', 'equipment_sport', 'protection_safety', 'protection_weather', 'furniture_carried', 'transportation_carried', 'transportation_stationary', 'push_cart', 'stroller', 'luggage');
CREATE TYPE groups AS ENUM ('group_1', 'group_2', 'group_3-7', 'group_8+');
CREATE TYPE objects AS ENUM ('animal', 'bag_carried', 'clothing_cultural', 'clothing_activity', 'goods_carried', 'equipment_construction', 'equipment_receational', 'equipment_sport', 'protection_safety', 'protection_weather', 'furniture_carried', 'transportation_carried', 'transportation_stationary', 'pushcart', 'stroller', 'luggage');

CREATE TABLE IF NOT EXISTS surveyors (
user_id UUID references public.users(user_id) NOT NULL,
Expand Down
14 changes: 8 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@
<label for="study-title">Study Title</label>
<input id="study-title" type="text" name="text">
</br>
<label for="study-start-date">Start Date</label>
<input id="study-start-date" type="text" name="text">
</br>
<label for="study-end-date">End Date</label>
<input id="study-end-date" type="text" name="text">
</br>
<label for="protocol-version-selection">Choose a version of the gehl protocol:</label>
<select id="protocol-version-selection">
<option value="1.0">1.0</option>
Expand All @@ -42,6 +36,14 @@ <h4>Invite Surveyor</h4>
<label for="surveyor-email">Surveyor Email</label>
<input id="surveyor-email" type="text">
</br>
<label for="study-start-date">Start Time:</label>
<input type="time" id="study-start-date" name="appt-time"
min="9:00" max="18:00" required />
</br>
<label for="study-end-date">End Time:</label>
<input type="time" id="study-end-date" name="appt-time"
min="9:00" max="18:00" required />
</br>
<input type="submit" value="Authorize Surveyor" >
</form>
</div>
Expand Down
68 changes: 66 additions & 2 deletions src/datastore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as dotenv from 'dotenv';
import * as pg from 'pg';
import * as uuidv4 from 'uuid/v4';

import { createStudy, createUser, giveUserSurveyAcess, Study, User, giveUserStudyAcess } from './datastore';
import { createStudy, createNewSurveyForStudy, createUser, addDataPointToSurvey, Study, User, giveUserStudyAcess } from './datastore';

dotenv.config();

Expand Down Expand Up @@ -57,6 +57,30 @@ const simpleStudyInvalidUserId: Study = {
protocolVersion: '1.0',
userId: uuidv4(),
}
export interface Survey {
studyId: string;
locationId: string;
surveyId: string;
startDate?: string,
endDate?: string,
timeCharacter?: string;
representation: string;
microclimate?: string;
temperatureCelcius?: number;
method: string;
userId?: string;
notes?: string;
}
const surveyNearGarbage: Survey = {
studyId: thorncliffeParkStudy.studyId,
locationId: uuidv4(),
surveyId: uuidv4(),
startDate: '2018-09-14T17:00:00Z',
endDate: '2018-09-14T19:00:00Z',
representation: 'absolute',
method: 'analog',
userId: sebastian.userId
}

const studyFields = ['gender', 'location'];

Expand Down Expand Up @@ -115,7 +139,47 @@ test('create new user if added to study without existsing account', async () =>
expect(userId).toBeTruthy();
expect(rowCount).toBe(1);
expect(command).toBe('INSERT');
})
});

test('save new survey', async () => {
const { rowCount, command } = await createNewSurveyForStudy(pool, surveyNearGarbage);
expect(rowCount).toBe(1);
expect(command).toBe('INSERT');
});

test('can save a data point', async () => {
const dataPoint = {
"location": {
"latitude": "43.70396934170554",
"longitude": "-79.3432493135333"
},
"object": "pushcart",
"posture": "sitting"
}
const { rowCount, command } = await addDataPointToSurvey(pool, surveyNearGarbage.studyId, surveyNearGarbage.surveyId, dataPoint);
expect(rowCount).toBe(1);
expect(command).toBe('INSERT');
});


test('transform another example of a data point', async () => {
const dataPoint = {
"gender": "male",
"groupSize": "pair",
"location": {
"latitude": "43.70416809098892",
"longitude": "-79.34354536235332"
},
"mode": "pedestrian",
"object": "luggage",
"posture": "leaning"
};
const { rowCount, command } = await addDataPointToSurvey(pool, surveyNearGarbage.studyId, surveyNearGarbage.surveyId, dataPoint);
expect(rowCount).toBe(1);
expect(command).toBe('INSERT');
});



afterAll(async () => {
try {
Expand Down
57 changes: 50 additions & 7 deletions src/datastore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ function studyIdToTablename(studyId: string) {

const genderLocationArray: GehlFields[] = ['gender', 'location'];
const genderLocation: Set<GehlFields> = new Set(genderLocationArray);
// to do this is very brittle, how do you now mess up objects vs object?
// also how about the connection between the enums defined at database creation time?
const allGehlFieldsArray: GehlFields[] = ['gender', 'age', 'mode', 'posture', 'activities', 'groups', 'objects', 'location']
const allGehlFields: Set<GehlFields> = new Set(allGehlFieldsArray);

Expand All @@ -96,20 +98,20 @@ function createNewTableFromGehlFields(study: Study, tablename: string, fields: G
switch (comparisionString) {
case setString(genderLocation):
return `CREATE TABLE ${tablename} (
survey_id UUID references data_collection.survey(survey_id),
survey_id UUID references data_collection.survey(survey_id) NOT NULL,
gender data_collection.gender,
location geometry
)`;
case setString(allGehlFields):
return `CREATE TABLE ${tablename} (
survey_id UUID references data_collection.survey(survey_id),
survey_id UUID references data_collection.survey(survey_id) NOT NULL,
gender data_collection.gender,
age data_collection.age,
mode data_collection.mode,
posture data_collection.posture,
activities data_collection.activities,
groups data_collection.groups,
objects data_collection.objects,
object data_collection.objects,
location geometry
)`;
default:
Expand Down Expand Up @@ -191,11 +193,52 @@ export async function giveUserStudyAcess(pool: pg.Pool, userEmail: string, study

export async function createNewSurveyForStudy(pool: pg.Pool, survey: Survey) {
const query = `INSERT INTO data_collection.survey
(study_id, survey_id, time_start, time_stop, representation, method, user_id)
VALUES('${survey.studyId}', '${survey.surveyId}', '${survey.startDate}', '${survey.endDate}', 'absolute', 'analog', '${survey.userId}')`;
(study_id, survey_id, time_start, time_stop, representation, method, user_id)
VALUES('${survey.studyId}', '${survey.surveyId}', '${survey.startDate}', '${survey.endDate}', '${survey.representation}', '${survey.method}', '${survey.userId}')`;
return pool.query(query);
}

export async function addDataPointToSurvey(pool: pg.Pool, surveyId: string) {
const query = `INSERT INTO "data_collection.${surveyId}"`;
function transformToPostgresInsert(dataPoint) {
const columns = Object.keys(dataPoint).map(key => {
if (key === 'groupSize') {
return 'groups';
} else {
return key;
}
});
const values = Object.keys(dataPoint).map(key => {
if (key === 'location') {
const longitude = dataPoint['location']['longitude'];
const latitude = dataPoint['location']['latitude'];
return `ST_GeomFromText('POINT(${longitude} ${latitude})', 4326)`;
} else if (key === 'groupSize') {
switch (dataPoint['groupSize']) {
case 'single':
return '\'group_1\'';
case 'pair':
return '\'group_2\'';
case 'group':
return '\'group_3-7\'';
case 'crowd':
return '\'group_8+\'';
default:
throw new Error(`invalid value for groupSize: ${dataPoint['groupSize']}`)
}
} else {
return `'${dataPoint[key]}'`;
}
})
return `(${(columns.join(', '))}) VALUES (${values.join(', ')})`;
}

export async function addDataPointToSurvey(pool: pg.Pool, studyId: string, surveyId: string, dataPoint: any) {
const tablename = studyIdToTablename(studyId);
const query = `INSERT INTO ${tablename}
${transformToPostgresInsert({ survey_id: surveyId, ...dataPoint })}`;
try {
return pool.query(query);
} catch (error) {
console.error(`error executing sql query: ${query}`)
throw error;
}
}
3 changes: 1 addition & 2 deletions src/gcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Request, Response } from 'express';
import * as pg from 'pg';
import * as uuidv4 from 'uuid/v4';

import { createNewSurveyForStudy, createStudy, createUser, giveUserStudyAcess, recordStudyStart } from './datastore';
import { createNewSurveyForStudy, createStudy, createUser, giveUserStudyAcess } from './datastore';

const pgConnectionInfo = {
connectionLimit: 1,
Expand Down Expand Up @@ -42,7 +42,6 @@ export async function saveNewSurvey(req: Request, res: Response) {
console.error(`failure to give user access for : ${req.body}| pg connection: ${JSON.stringify(pgConnectionInfo)}`);
throw error;
}

}

export async function addSurveyorToStudy(req: Request, res: Response) {
Expand Down

0 comments on commit fd14cbe

Please sign in to comment.