Skip to content

Commit

Permalink
Add grade distros json field (nrRoutesByGrade) to crag entity.
Browse files Browse the repository at this point in the history
  • Loading branch information
salamca committed Jan 21, 2024
1 parent 04f48cc commit 642fa1e
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 3 deletions.
19 changes: 17 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"dotenv": "^16.0.3",
"fs": "0.0.1-security",
"graphql": "^16.6.0",
"graphql-type-json": "^0.3.2",
"handlebars": "^4.7.7",
"hbs": "^4.2.0",
"ioredis": "^5.2.3",
Expand Down
5 changes: 5 additions & 0 deletions src/crags/entities/crag.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { GradingSystem } from './grading-system.entity';
import { User } from '../../users/entities/user.entity';
import { EntityStatus } from './enums/entity-status.enum';
import { PublishStatus } from './enums/publish-status.enum';
import GraphQLJSON from 'graphql-type-json';

export enum CragType {
SPORT = 'sport',
Expand Down Expand Up @@ -263,4 +264,8 @@ export class Crag extends BaseEntity {
@JoinColumn()
@Field(() => Image, { nullable: true })
coverImage: Promise<Image>;

@Column({ type: 'jsonb', nullable: true })
@Field((type) => GraphQLJSON, { nullable: true })
nrRoutesByGrade: JSON;
}
2 changes: 1 addition & 1 deletion src/crags/services/crags.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export class CragsService {
routeTypeId: params.routeTypeId,
});
}
console.log(builder.getSql());

setBuilderCache(builder);

return builder;
Expand Down
104 changes: 104 additions & 0 deletions src/migration/1705839051844-addNrRoutesByGradeToCrag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

type TGrade = {
id: string;
difficulty: number;
name: string;
gradingSystemId: string;
};

export class addNrRoutesByGradeToCrag1705839051844
implements MigrationInterface
{
name = 'addNrRoutesByGradeToCrag1705839051844';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "crag" ADD "nr_routes_by_grade" jsonb`,
);

// Get all grading systems and grades
const gradingSystems = await queryRunner.query(
`SELECT * FROM grading_system gs ORDER BY gs.position ASC`,
);

for (const gradingSystem of gradingSystems) {
const grades = await queryRunner.query(
`SELECT * FROM grade g WHERE grading_system_id = '${gradingSystem.id}' ORDER BY g.difficulty ASC`,
);

gradingSystem.grades = grades;
}

// Calculate all grade distros for all crags
const crags = await queryRunner.query('SELECT id FROM crag');
for (const crag of crags) {
const routes = await queryRunner.query(
`SELECT difficulty FROM route WHERE crag_id = '${crag.id}'`,
);

const roundedDiffCountsByGradingSystem = {};

for (const gradingSystem of gradingSystems) {
const grades = gradingSystem.grades;
roundedDiffCountsByGradingSystem[gradingSystem.id] = {};

for (let route of routes) {
if (route.isProject) continue;

const grade = await this.difficultyToGrade(route.difficulty, grades);

if (
roundedDiffCountsByGradingSystem[gradingSystem.id][
grade.difficulty
] === undefined
) {
roundedDiffCountsByGradingSystem[gradingSystem.id][
grade.difficulty
] = 1;
} else {
roundedDiffCountsByGradingSystem[gradingSystem.id][
grade.difficulty
]++;
}
}
}

await queryRunner.query(
`UPDATE crag SET nr_routes_by_grade = '${JSON.stringify(
roundedDiffCountsByGradingSystem,
)}' WHERE id = '${crag.id}'`,
);
}
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "crag" DROP COLUMN "nr_routes_by_grade"`,
);
}

private async difficultyToGrade(difficulty: number, grades: TGrade[]) {
let prevGrade: TGrade;
let currGrade: TGrade;
// assuming grades are ordered by difficulty low to high
for (let i = 1; i < grades.length; i++) {
prevGrade = grades[i - 1];
currGrade = grades[i];

if (currGrade.difficulty >= difficulty) {
// are we closer to left or right 'whole' grade
if (
difficulty - prevGrade.difficulty <=
currGrade.difficulty - difficulty
) {
return prevGrade;
} else {
return currGrade;
}
}
}
// fallback to last (max) grade if this grading system does not have a grade of such difficulty
return currGrade;
}
}

0 comments on commit 642fa1e

Please sign in to comment.