Skip to content

Commit

Permalink
chore(api): scenario-cost-surface
Browse files Browse the repository at this point in the history
  • Loading branch information
kgajowy committed Jun 14, 2021
1 parent dc6ac38 commit 26507e2
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ import { Module } from '@nestjs/common';
import { CostSurfaceViewService } from './cost-surface-view.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { PlanningUnitsGeom } from '@marxan-jobs/planning-unit-geometry';
import { ScenariosPlanningUnitGeoEntity } from '@marxan/scenarios-planning-unit';
import {
ScenariosPlanningUnitGeoEntity,
ScenariosPuCostDataGeo,
} from '@marxan/scenarios-planning-unit';
import { DbConnections } from '@marxan-api/ormconfig.connections';

@Module({
imports: [
TypeOrmModule.forFeature(
[PlanningUnitsGeom, ScenariosPlanningUnitGeoEntity],
[
PlanningUnitsGeom,
ScenariosPlanningUnitGeoEntity,
ScenariosPuCostDataGeo,
],
DbConnections.geoprocessingDB,
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ export class CostSurfaceViewService {
private readonly spuDataRepo: Repository<ScenariosPlanningUnitGeoEntity>,
) {}

async read(scenarioId: string, stream: stream.Writable): Promise<void> {
stream.write('id\tcost\tstatus');
async read(
scenarioId: string,
responseStream: stream.Writable,
): Promise<void> {
responseStream.write('id\tcost\tstatus');

// TODO make some changes upon lockin_status
// TODO add _costs rows
const query = await this.spuDataRepo
.createQueryBuilder('spu')
.select(['spu.puid', 'spu.lockin_status', 'spucd.cost'])
Expand All @@ -31,34 +32,22 @@ export class CostSurfaceViewService {
.where(`spu.scenario_id = :scenarioId`, { scenarioId });

const queryStream = await query.stream();
// typeorm query runner/builder -> stream

queryStream.on('data', (data) => {
const row = (data as unknown) as {
// "pipe" does not seem to trigger
queryStream.on(
'data',
(data: {
puid: number;
lockin_status: number | null;
cost: number | null;
};
const tsvRow = [row.puid, row.lockin_status, row.cost].join('\t');
stream.write(`\n`);
stream.write(tsvRow);
});
queryStream.on('result', (data) => {
console.log(`-result`, data);
});
queryStream.on('end', () => {
// queryRunner.release();
stream.end();
console.log(`-end`);
});
queryStream.on('error', (error) => {
// queryRunner.release();
stream.destroy(error);
console.log(`-error`, error);
});
}) => {
const tsvRow = [data.puid, data.cost, data.lockin_status].join('\t');
responseStream.write(`\n`);
responseStream.write(tsvRow);
},
);

stream.on(`finish`, () => {
console.log(`finished?`);
queryStream.on('end', () => {
responseStream.end();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,21 @@ describe(`When scenario has PUs with cost and lock status`, () => {

it(`returns relevant data`, async () => {
const result = await world.WhenGettingMarxanData();
expect(result).toMatchInlineSnapshot(`
"id cost status
0
1
2
3 "
console.log(`---- result`, result);
const [headers, ...costAndStatus] = result.split('\n');

expect(headers).toEqual('id\tcost\tstatus');
expect(costAndStatus).toMatchInlineSnapshot(`
Array [
"0 ",
"1 ",
"2 ",
"3 ",
]
`);
});
});

afterAll(async () => {
await world?.cleanup();
// await world?.cleanup();
});
66 changes: 54 additions & 12 deletions api/apps/api/test/scenario-cost-surface/world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { GivenUserIsLoggedIn } from '../steps/given-user-is-logged-in';
import * as request from 'supertest';
import { In, Repository } from 'typeorm';
import { getRepositoryToken } from '@nestjs/typeorm';
import { ScenariosPlanningUnitGeoEntity } from '@marxan/scenarios-planning-unit';
import {
LockStatus,
ScenariosPlanningUnitGeoEntity,
ScenariosPuCostDataGeo,
} from '@marxan/scenarios-planning-unit';
import { Polygon } from 'geojson';
import { v4 } from 'uuid';
import { DbConnections } from '@marxan-api/ormconfig.connections';
import {
PlanningUnitsGeom,
Expand All @@ -14,6 +17,7 @@ import {
import { GivenProjectExists } from '../steps/given-project';
import { ScenariosTestUtils } from '../utils/scenarios.test.utils';
import { ScenarioType } from '@marxan-api/modules/scenarios/scenario.api.entity';
import { v4 } from 'uuid';

export const createWorld = async () => {
const app = await bootstrapApplication();
Expand All @@ -29,7 +33,9 @@ export const createWorld = async () => {
projectId,
})
).data.id;
console.log(`--- scenarioId`, scenarioId);
const geometries: string[] = [];
const scenariosPuData: string[] = [];

const puGeometryRepo: Repository<PlanningUnitsGeom> = app.get(
getRepositoryToken(PlanningUnitsGeom, DbConnections.geoprocessingDB),
Expand All @@ -40,11 +46,18 @@ export const createWorld = async () => {
DbConnections.geoprocessingDB,
),
);
const scenarioPuDataCostRepo: Repository<ScenariosPuCostDataGeo> = app.get(
getRepositoryToken(ScenariosPuCostDataGeo, DbConnections.geoprocessingDB),
);
console.log(`--- world ok`);

return {
cleanup: async () => {
await ScenariosTestUtils.deleteScenario(app, jwt, scenarioId);
await projectCleanup();
await scenarioPuDataCostRepo.delete({
scenariosPuDataId: In(scenariosPuData),
});
await puGeometryRepo.delete({
id: In(geometries),
});
Expand All @@ -54,6 +67,7 @@ export const createWorld = async () => {
await app.close();
},
GivenScenarioWithPuAndLocks: async () => {
console.log(`-----\t-------1`);
const polygons: Polygon[] = [1, 2, 3, 4].map((i) => ({
type: 'Polygon',
coordinates: [
Expand All @@ -66,26 +80,54 @@ export const createWorld = async () => {
],
],
}));
const geoRows = (
await puGeometryRepo.insert(
polygons.map((poly) => ({
theGeom: () =>
`st_multi(ST_GeomFromGeoJSON('${JSON.stringify(poly)}'))`,
type: ShapeType.Square,
})),
)
).identifiers;
console.log(`-----\t-------2`);
let geoRows: Record<string, string>[] = [];
try {
geoRows = (
await puGeometryRepo.insert(
polygons.map((poly) => ({
theGeom: () =>
`st_multi(ST_GeomFromGeoJSON('${JSON.stringify(poly)}'))`,
type: ShapeType.Square,
})),
)
).identifiers;
} catch (error) {
console.log(error);
console.error(error);
}

console.log(`-----\t-------3`);
geometries.push(...geoRows.map((geo) => geo.id));
await scenarioPuDataRepo.save(
const scenarioPuData = await scenarioPuDataRepo.save(
geometries.map((id, index) =>
scenarioPuDataRepo.create({
puGeometryId: id,
scenarioId,
planningUnitMarxanId: index,
lockStatus: LockStatus.LockedIn,
// lockStatus:
// index === 0
// ? LockStatus.Unstated
// : index === 1
// ? LockStatus.LockedIn
// : LockStatus.LockedOut,
}),
),
);
console.log(`-----\t-------4`);
console.log(`scenarioPuData`, scenarioPuData);
scenariosPuData.push(...scenarioPuData.map((spud) => spud.id));
const costs = await scenarioPuDataCostRepo.save(
scenarioPuData.map((spud, index) => ({
cost: (index + 1) * 200,
scenariosPuDataId: spud.id,
scenariosPlanningUnit: spud,
planningUnitId: v4(),
})),
);

console.log(`costs`, costs);
},
WhenGettingMarxanData: async () =>
(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { flatten } from 'lodash';

import { CostSurfacePersistencePort } from '../ports/persistence/cost-surface-persistence.port';
import { PlanningUnitCost } from '../ports/planning-unit-cost';
import { ScenariosPuCostDataGeo } from '../../scenarios/scenarios-pu-cost-data.geo.entity';
import { ScenariosPuCostDataGeo } from '@marxan/scenarios-planning-unit';

@Injectable()
export class TypeormCostSurface implements CostSurfacePersistencePort {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import { ShapefileConverterPort } from './ports/shapefile-converter/shapefile-co

import { TypeormCostSurface } from './adapters/typeorm-cost-surface';
import { ShapefileConverter } from './adapters/shapefile-converter';
import { ScenariosPuCostDataGeo } from '../scenarios/scenarios-pu-cost-data.geo.entity';
import { PuCostExtractor } from './adapters/pu-cost-extractor';
import { AvailablePlanningUnitsRepository } from './adapters/available-planning-units-repository';
import { ScenariosPuCostDataGeo } from '@marxan/scenarios-planning-unit';

@Module({
imports: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { v4 } from 'uuid';

import { ScenariosPuCostDataGeo } from '@marxan-geoprocessing/modules/scenarios/scenarios-pu-cost-data.geo.entity';
import { ScenariosPlanningUnitGeoEntity } from '@marxan/scenarios-planning-unit';
import {
ScenariosPlanningUnitGeoEntity,
ScenariosPuCostDataGeo,
} from '@marxan/scenarios-planning-unit';

import { GivenScenarioPuDataExists } from '../../steps/given-scenario-pu-data-exists';

Expand Down
1 change: 1 addition & 0 deletions api/libs/scenarios-planning-unit/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { LockStatus } from './lock-status.enum';
export { ScenariosPlanningUnitGeoEntity } from './scenarios-planning-unit.geo.entity';
export { ScenariosPuCostDataGeo } from './scenarios-pu-cost-data.geo.entity';
export * from './domain';

0 comments on commit 26507e2

Please sign in to comment.