Skip to content

Commit

Permalink
Implement random search
Browse files Browse the repository at this point in the history
  • Loading branch information
ledyba committed Jul 23, 2021
1 parent ea971d3 commit dbb97f8
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 25 deletions.
27 changes: 10 additions & 17 deletions client/src/omote/layers/Index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,8 @@ export default class Index extends Layer {
this.fixTooltipPosition_();
}
}
/**
* @private
*/
fixTooltipPosition_() {

private fixTooltipPosition_() {
const tooltip = this.tooltip_;
const m = this.selected_;
if(m == null) {
Expand All @@ -93,8 +91,7 @@ export default class Index extends Layer {
}
}

/** @override */
onAttached() {
override onAttached() {
this.world.cursor = false;
this.world.canvas.addEventListener('wheel', this.wheelEventListener_, false);
this.world.canvas.addEventListener('mousemove', this.mouseMoveListener_, false);
Expand All @@ -105,8 +102,8 @@ export default class Index extends Layer {
this.mouseX_ = NaN;
this.mouseY_ = NaN;
}
/** @override */
onDetached() {

override onDetached() {
this.mouseX_ = NaN;
this.mouseY_ = NaN;
this.world.cursor = false;
Expand All @@ -115,7 +112,7 @@ export default class Index extends Layer {
this.world.canvas.removeEventListener('mouseup', this.mouseUpListener_, false);
}

onMouseMove_(ev: MouseEvent) {
private onMouseMove_(ev: MouseEvent) {
ev.preventDefault();
const canvas = this.world.canvas;
const hw = canvas.width/2;
Expand All @@ -125,7 +122,7 @@ export default class Index extends Layer {
this.mouseY_ = -(ev.clientY - hh) / hh;
}

onMouseUp_(ev: MouseEvent) {
private onMouseUp_(ev: MouseEvent) {
ev.preventDefault();
const m = this.selected_;
if(!m) {
Expand All @@ -135,11 +132,7 @@ export default class Index extends Layer {
this.world.pushLayer(new Page(this.world, m.path, content));
}

/**
*
* @param {WheelEvent} event
*/
onWheelEvent_(event: WheelEvent) {
private onWheelEvent_(event: WheelEvent) {
event.preventDefault();
const world = this.world;
let dx = event.deltaX;
Expand All @@ -166,7 +159,7 @@ export default class Index extends Layer {
}
}

onLoadMoments_(moments: protocol.Moment.Search.Response[]) {
private onLoadMoments_(moments: protocol.Moment.Search.Response[]) {
const world = this.world;
const models: Moment[] = [];
for(let m of moments) {
Expand All @@ -179,7 +172,7 @@ export default class Index extends Layer {
}

fetch(size: number) {
fetch(`/moment/search?size=${size}`)
fetch(`/moments/random?size=${size}`)
.then(resp => resp.json())
.then(this.onLoadMoments_.bind(this));
}
Expand Down
9 changes: 8 additions & 1 deletion server/src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Shelf from './shelf/Shelf';
// Omote Controllers
import OmoteIndexController from './controller/omote/IndexController';
import MomentController from './controller/omote/MomentController';
import RandomSelectionController, {RandomSelectionControllerInterface} from './controller/omote/RandomSelectionController';
// Ura Controllers
import UraIndexController from './controller/ura/IndexController';
import MomentListController, {MomentListControllerInterface} from './controller/ura/MomentListController';
Expand Down Expand Up @@ -114,6 +115,12 @@ class Server {
},
});
}
{ // (omote)/moments/random
const omote = await RandomSelectionController.create(this.shelf);
this.omote.get<RandomSelectionControllerInterface>('/moments/random', async (req, reply) => {
await omote.handle(req, reply);
});
}
{ // (both)/moment/year/month/day/HH:mm:ss/
const c = await MomentBodyController.create(this.shelf);
this.both.get('/moment/:year(^[0-9]{4}$)/:month(^[0-9]{2}$)/:day(^[0-9]{2}$)/:time(^[0-9]{2}:[0-9]{2}:[0-9]{2}$)/', async (req, reply) => {
Expand Down Expand Up @@ -165,7 +172,7 @@ class Server {
await ura.handle(req, reply);
});
}
{ // file uploads
{ // (ura)/upload
const ura = await UploadController.create(this.shelf);
this.ura.post('/upload', async(req, reply) => {
await ura.handle(req, reply);
Expand Down
45 changes: 45 additions & 0 deletions server/src/controller/omote/RandomSelectionController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {FastifyReply, FastifyRequest, RequestGenericInterface} from 'fastify';

import * as protocol from 'lib/protocol';

import Shelf from '../../shelf/Shelf';
import {formatMomentPath, formatMomentTime, MomentSummary} from '../../shelf/Moment';

export interface RandomSelectionControllerInterface extends RequestGenericInterface {
Querystring: {
size: string,
}
}

export default class RandomSelectionController {
private readonly shelf: Shelf;
private constructor(shelf: Shelf) {
this.shelf = shelf;
}
static async create(shelf: Shelf): Promise<RandomSelectionController> {
return new RandomSelectionController(shelf);
}
async handle(req: FastifyRequest<RandomSelectionControllerInterface>, reply: FastifyReply) {
const size = parseInt(req.query.size, 10);
const moments: MomentSummary[] = await this.shelf.findMomentSummariesByRandom(size);
const results: protocol.Moment.Search.Response[] = [];
for (const m of moments) {
if(m.iconID === undefined) {
continue;
}
const p = formatMomentPath(m.timestamp!!);
results.push({
angle: 0.0,
date: formatMomentTime(m.timestamp!!),
title: m.title,
path: p,
imageURL: `/entity/${m.iconID}/icon`,
bodyURL: `/moment${p}`,
});
}
reply
.type('application/json')
.code(200)
.send(results);
}
}
2 changes: 1 addition & 1 deletion server/src/controller/ura/MomentListController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default class MomentListController {
}
async handle(req: FastifyRequest<MomentListControllerInterface>, reply: FastifyReply) {
const year = parseInt(req.params.year, 10) || dayjs().year();
const moments = (await this.shelf.findMomentsInYear(year)).map((it) => {
const moments = (await this.shelf.findMomentSummariesInYear(year)).map((it) => {
return {
iconID: it.iconID || '',
path: formatMomentPath(it.timestamp!!),
Expand Down
23 changes: 19 additions & 4 deletions server/src/repo/Repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ where "timestamp" = $6;
]);
}

async findMomentsInYear(year: number): Promise<MomentSummary[]> {
async findMomentSummariesInYear(year: number): Promise<MomentSummary[]> {
// language=PostgreSQL
const q=`
select timestamp, title, icon_id from moments
Expand All @@ -180,6 +180,21 @@ where
return moments;
}

async findMomentSummariesByRandom(size: number): Promise<MomentSummary[]> {
// https://stackoverflow.com/a/41337788
// language=PostgreSQL
const q=`
select timestamp, title, icon_id from moments
TABLESAMPLE SYSTEM_ROWS($1);
`;
const moments: MomentSummary[] = [];
const rows = await this.pool.query(q, [size]);
for await (const row of rows) {
moments.push(decodeMomentSummary(row));
}
return moments;
}

async findMoment(timestamp: dayjs.Dayjs): Promise<Moment | null> {
// language=PostgreSQL
const q=`
Expand Down Expand Up @@ -209,15 +224,15 @@ function decodeMoment(row: ResultRow): Moment {
title: row.get('title') as string || '',
author: row.get('author') as string || '',
text: row.get('text') as string || '',
iconID: row.get('icon_id') as (string | undefined),
iconID: row.get('icon_id') as (string | null) || undefined,
};
}

function decodeMomentSummary(row: ResultRow): MomentSummary {
return {
timestamp: dayjs(row.get('timestamp') as Date),
title: row.get('title') as string,
iconID: row.get('icon_id') as (string | undefined),
title: row.get('title') as string || '',
iconID: row.get('icon_id') as (string | null) || undefined,
};
}

Expand Down
7 changes: 5 additions & 2 deletions server/src/shelf/Shelf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,15 @@ class Shelf {
}
return m;
}
async findMomentsInYear(year: number): Promise<MomentSummary[]> {
return await this.repo.findMomentsInYear(year);
async findMomentSummariesInYear(year: number): Promise<MomentSummary[]> {
return await this.repo.findMomentSummariesInYear(year);
}
async findMoment(timestamp: dayjs.Dayjs): Promise<Moment | null> {
return await this.repo.findMoment(timestamp);
}
async findMomentSummariesByRandom(size: number): Promise<MomentSummary[]> {
return await this.repo.findMomentSummariesByRandom(size);
}
async deleteMoment(timestamp: dayjs.Dayjs): Promise<boolean> {
return await this.repo.deleteMoment(timestamp);
}
Expand Down

0 comments on commit dbb97f8

Please sign in to comment.