forked from trent_larson/crowd-funder-for-time-pwa
fix a problem with test data (divide by 0), and map full addresses to points
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
- top screens from img/screens.pdf milestone:2 :
|
- top screens from img/screens.pdf milestone:2 :
|
||||||
- view all :
|
- view all :
|
||||||
- add infinite scroll assignee:matthew
|
- add infinite scroll assignee:matthew
|
||||||
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
|
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
|
||||||
|
|
||||||
- replace user-affecting console.logs with error messages (eg. catches)
|
- replace user-affecting console.log & console.error with error messages (eg. catches)
|
||||||
|
|
||||||
- stats v1 :
|
- stats v1 :
|
||||||
- use all bits of randomness for location
|
- use all bits of randomness for location
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
- Release Minimum Viable Product :
|
- Release Minimum Viable Product :
|
||||||
- Turn off stats-world or ensure it's usable (eg. cannot zoom out too far and lose world, cannot screenshot).
|
- Turn off stats-world or ensure it's usable (eg. cannot zoom out too far and lose world, cannot screenshot).
|
||||||
- Add disclaimers.
|
- Add disclaimers.
|
||||||
|
- Switch default server to the public server.
|
||||||
- Deploy to a server.
|
- Deploy to a server.
|
||||||
- Ensure public server has limits that work for group adoption.
|
- Ensure public server has limits that work for group adoption.
|
||||||
- Test PWA features on Android and iOS.
|
- Test PWA features on Android and iOS.
|
||||||
@@ -52,7 +54,9 @@
|
|||||||
- linking between projects or plans :
|
- linking between projects or plans :
|
||||||
- terminology:
|
- terminology:
|
||||||
- Fulfills, Feeds, contributes to, supplies, boosts, advances
|
- Fulfills, Feeds, contributes to, supplies, boosts, advances
|
||||||
- Precedes, comes before, is sought by vs follows, seeks, builds on ("contributes to" isn't specific enough, "succeeds" has different confusing meaning)
|
- Precedes, comes before, is sought by -- vs follows, seeks, builds on ("contributes to" isn't specific enough, "succeeds" has different, possibly confusing meaning)
|
||||||
|
|
||||||
|
- automated tests, eg. cypress
|
||||||
|
|
||||||
- Notifications (wake on the phone, push notifications)
|
- Notifications (wake on the phone, push notifications)
|
||||||
|
|
||||||
@@ -64,5 +68,7 @@
|
|||||||
|
|
||||||
- DIDComm
|
- DIDComm
|
||||||
|
|
||||||
|
- Write to or read from a different ledger (eg. private ACDC, attest.sh)
|
||||||
|
|
||||||
- v video for multiple identities https://youtu.be/p8L87AeD76w
|
- v video for multiple identities https://youtu.be/p8L87AeD76w
|
||||||
- v video for adding time to contacts https://youtu.be/7Yylczevp10
|
- v video for adding time to contacts https://youtu.be/7Yylczevp10
|
||||||
|
|||||||
@@ -10,33 +10,33 @@ import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
|||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
|
|
||||||
const ANIMATION_DURATION_SECS = 10;
|
const ANIMATION_DURATION_SECS = 10;
|
||||||
const BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
||||||
const ENDORSER_ENTITY_PREFIX = "https://endorser.ch/entity/";
|
const ENDORSER_ENTITY_PREFIX = "https://endorser.ch/entity/";
|
||||||
|
|
||||||
export async function loadLandmarks(vue, world, scene, loop) {
|
export async function loadLandmarks(vue, world, scene, loop) {
|
||||||
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await db.open();
|
||||||
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||||
const activeDid = settings?.activeDid || "";
|
const activeDid = settings?.activeDid || "";
|
||||||
|
const apiServer = settings?.apiServer;
|
||||||
await accountsDB.open();
|
await accountsDB.open();
|
||||||
const accounts = await accountsDB.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
const account = R.find((acc) => acc.did === activeDid, accounts);
|
const account = R.find((acc) => acc.did === activeDid, accounts);
|
||||||
const identity = JSON.parse(account?.identity || "undefined");
|
const identity = JSON.parse(account?.identity || "undefined");
|
||||||
const token = await accessToken(identity);
|
const token = await accessToken(identity);
|
||||||
|
|
||||||
const url =
|
const url = apiServer + "/api/v2/report/claims?claimType=GiveAction";
|
||||||
endorserApiServer + "/api/v2/report/claims?claimType=GiveAction";
|
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: "Bearer " + token,
|
Authorization: "Bearer " + token,
|
||||||
};
|
};
|
||||||
const resp = await axios.get(url, { headers: headers });
|
const resp = await axios.get(url, { headers: headers });
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const minDate = resp.data.data[resp.data.data.length - 1].issuedAt;
|
const landmarks = resp.data.data;
|
||||||
const maxDate = resp.data.data[0].issuedAt;
|
const minDate = landmarks[landmarks.length - 1].issuedAt;
|
||||||
|
const maxDate = landmarks[0].issuedAt;
|
||||||
const minTimeMillis = new Date(minDate).getTime();
|
const minTimeMillis = new Date(minDate).getTime();
|
||||||
const fullTimeMillis = new Date(maxDate).getTime() - minTimeMillis;
|
const fullTimeMillis =
|
||||||
|
maxDate > minDate ? new Date(maxDate).getTime() - minTimeMillis : 1; // avoid divide by zero
|
||||||
// ratio of animation time to real time
|
// ratio of animation time to real time
|
||||||
const fakeRealRatio = (ANIMATION_DURATION_SECS * 1000) / fullTimeMillis;
|
const fakeRealRatio = (ANIMATION_DURATION_SECS * 1000) / fullTimeMillis;
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ export async function loadLandmarks(vue, world, scene, loop) {
|
|||||||
// modScale = 15;
|
// modScale = 15;
|
||||||
|
|
||||||
// calculate positions for each claim, especially because some are random
|
// calculate positions for each claim, especially because some are random
|
||||||
const locations = resp.data.data.map((claim) =>
|
const locations = landmarks.map((claim) =>
|
||||||
locForGive(claim, world.PLATFORM_SIZE, world.PLATFORM_EDGE_FOR_UNKNOWNS)
|
locForGive(claim, world.PLATFORM_SIZE, world.PLATFORM_EDGE_FOR_UNKNOWNS)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -62,9 +62,9 @@ export async function loadLandmarks(vue, world, scene, loop) {
|
|||||||
modelLoc,
|
modelLoc,
|
||||||
function (gltf) {
|
function (gltf) {
|
||||||
gltf.scene.scale.set(0, 0, 0);
|
gltf.scene.scale.set(0, 0, 0);
|
||||||
for (let i = 0; i < resp.data.data.length; i++) {
|
for (let i = 0; i < landmarks.length; i++) {
|
||||||
// claim is a GiveServerRecord (see endorserServer.ts)
|
// claim is a GiveServerRecord (see endorserServer.ts)
|
||||||
const claim = resp.data.data[i];
|
const claim = landmarks[i];
|
||||||
const newPlant = SkeletonUtils.clone(gltf.scene);
|
const newPlant = SkeletonUtils.clone(gltf.scene);
|
||||||
|
|
||||||
const loc = locations[i];
|
const loc = locations[i];
|
||||||
@@ -88,9 +88,9 @@ export async function loadLandmarks(vue, world, scene, loop) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// calculate when lights shine on appearing claim area
|
// calculate when lights shine on appearing claim area
|
||||||
for (let i = 0; i < resp.data.data.length; i++) {
|
for (let i = 0; i < landmarks.length; i++) {
|
||||||
// claim is a GiveServerRecord (see endorserServer.ts)
|
// claim is a GiveServerRecord (see endorserServer.ts)
|
||||||
const claim = resp.data.data[i];
|
const claim = landmarks[i];
|
||||||
|
|
||||||
const loc = locations[i];
|
const loc = locations[i];
|
||||||
const light = createLight();
|
const light = createLight();
|
||||||
@@ -157,7 +157,7 @@ function locForGive(giveClaim, platformWidth, borderWidth) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!loc) {
|
if (!loc) {
|
||||||
// it must be outside our known addresses so let's put it somewhere random
|
// it must be outside our known addresses so let's put it somewhere random on the side
|
||||||
const leftSide = Math.random() < 0.5;
|
const leftSide = Math.random() < 0.5;
|
||||||
loc = {
|
loc = {
|
||||||
x: leftSide
|
x: leftSide
|
||||||
@@ -170,34 +170,49 @@ function locForGive(giveClaim, platformWidth, borderWidth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a deterministic x & z location based on the randomness in a ULID.
|
* Generate a deterministic x & z location based on the randomness of an ID.
|
||||||
*
|
*
|
||||||
* We'll use the first 20 bits for the x coordinate and next 20 for the z.
|
* We'd like the location to fully map back to the original ID.
|
||||||
* That's a bit over a trillion locations... should be enough for pretty
|
* This typically means we use half the ID for the x and half for the z.
|
||||||
* unique locations for this fun kind of application within a network
|
*
|
||||||
* -- though they're not guaranteed unique without the full ID.
|
* ... in this case: a ULID.
|
||||||
* (We're leaving 40 bits for other properties.)
|
* We'll use the first half (13 characters) for the x coordinate and next 13 for the z.
|
||||||
|
* We recognize that this is only 3 characters = 15 bits = 32768 unique values
|
||||||
|
* for the random part for the first half. We also recognize that those random
|
||||||
|
* bits may be shared with previous ULIDs if they were generated in the same
|
||||||
|
* millisecond, and therefore much of the evenness of the distribution depends
|
||||||
|
* on the other dimension.
|
||||||
|
*
|
||||||
|
* Also: since the first 10 characters are time-based, we're going to reverse
|
||||||
|
* the order of the characters to make the randomness more evenly distributed.
|
||||||
|
* This is reversing the order of the 5-bit characters, not each of the bits.
|
||||||
|
* Also wik: the first characters of the second half might be the same as
|
||||||
|
* previous ULIDs if they were generated in the same millisecond. So it's
|
||||||
|
* best to have that last character be the most significant bit so that there
|
||||||
|
* is a more even distribution in that dimension.
|
||||||
*
|
*
|
||||||
* @param ulid
|
* @param ulid
|
||||||
* @returns {x: float, z: float} where 0 <= x & z < 100
|
* @returns {x: float, z: float} where 0 <= x & z < 100
|
||||||
*/
|
*/
|
||||||
function locForUlid(ulid) {
|
function locForUlid(ulid) {
|
||||||
// The random parts of a ULID come after the first 10 characters.
|
const xChars = ulid.substring(0, 13).split("").reverse().join("");
|
||||||
const randomness = ulid.substring(10);
|
const zChars = ulid.substring(13, 26).split("").reverse().join("");
|
||||||
|
|
||||||
// That leaves 16 characters of randomness, or 80 bits.
|
// from https://github.com/ulid/javascript/blob/5e9727b527aec5b841737c395a20085c4361e971/lib/index.ts#L21
|
||||||
|
const BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; // Crockford's Base32
|
||||||
|
|
||||||
// We're currently only using 32 possible x and z values
|
// We're currently only using 1024 possible x and z values
|
||||||
// because the display is pretty low-fidelity at this point.
|
// because the display is pretty low-fidelity at this point.
|
||||||
|
const rawX = BASE32.indexOf(xChars[1]) * 32 + BASE32.indexOf(xChars[0]);
|
||||||
|
const rawZ = BASE32.indexOf(zChars[1]) * 32 + BASE32.indexOf(zChars[0]);
|
||||||
|
|
||||||
// Similar code is below.
|
const x = (100 * rawX) / 1024;
|
||||||
const x = (100 * BASE32.indexOf(randomness.substring(0, 1))) / 32;
|
const z = (100 * rawZ) / 1024;
|
||||||
const z = (100 * BASE32.indexOf(randomness.substring(4, 5))) / 32;
|
|
||||||
return { x, z };
|
return { x, z };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See locForUlid
|
* See locForUlid. Similar, but for ethr DIDs.
|
||||||
* @param did
|
* @param did
|
||||||
* @returns {x: float, z: float} where 0 <= x & z < 100
|
* @returns {x: float, z: float} where 0 <= x & z < 100
|
||||||
*/
|
*/
|
||||||
@@ -206,13 +221,15 @@ function locForEthrDid(did) {
|
|||||||
if (did.length < 51) {
|
if (did.length < 51) {
|
||||||
return { x: 0, z: 0 };
|
return { x: 0, z: 0 };
|
||||||
} else {
|
} else {
|
||||||
const randomness = did.substring(11);
|
const randomness = did.substring("did:ethr:0x".length);
|
||||||
// We'll take the first 4 bits for 16 possible x & z values.
|
// We'll use all the randomness for fully unique x & z values.
|
||||||
const xOff = parseInt(Number("0x" + randomness.substring(0, 1)), 10);
|
// But we'll only calculate this view with the first byte since our rendering resolution is low.
|
||||||
const x = (xOff * 100) / 16;
|
const xOff = parseInt(Number("0x" + randomness.substring(0, 2)), 10);
|
||||||
// ... and since we're reserving 20 bits total for x, start with character 5.
|
const x = (xOff * 100) / 256;
|
||||||
const zOff = parseInt(Number("0x" + randomness.substring(5, 6)), 10);
|
// ... and since we're reserving 20 bytes total for x, start z with character 20,
|
||||||
const z = (zOff * 100) / 16;
|
// again with one byte.
|
||||||
|
const zOff = parseInt(Number("0x" + randomness.substring(20, 22)), 10);
|
||||||
|
const z = (zOff * 100) / 256;
|
||||||
return { x, z };
|
return { x, z };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ function createRenderer() {
|
|||||||
const renderer = new WebGLRenderer({ antialias: true });
|
const renderer = new WebGLRenderer({ antialias: true });
|
||||||
|
|
||||||
// turn on the physically correct lighting model
|
// turn on the physically correct lighting model
|
||||||
// (The browser complains: "THREE.WebGLRenderer: .physicallyCorrectLights has been removed. Set enderer.useLegacyLights instead." However, that changes the lighting in a way that doesn't look better.)
|
// (The browser complains: "THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead." However, that changes the lighting in a way that doesn't look better.)
|
||||||
renderer.physicallyCorrectLights = true;
|
renderer.physicallyCorrectLights = true;
|
||||||
|
|
||||||
return renderer;
|
return renderer;
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
/* import * as R from "ramda";
|
|
||||||
import { configureStore, createSlice } from "@reduxjs/toolkit";
|
|
||||||
import { IIdentifier } from "@veramo/core";
|
|
||||||
|
|
||||||
import { Contact } from "../entity/contact";
|
|
||||||
import { Settings } from "../entity/settings";
|
|
||||||
import * as utility from "../utility/utility";
|
|
||||||
|
|
||||||
const MAX_LOG_LENGTH = 2000000;
|
|
||||||
|
|
||||||
export const DEFAULT_ENDORSER_API_SERVER = "https://endorser.ch:3000";
|
|
||||||
export const DEFAULT_ENDORSER_VIEW_SERVER = "https://endorser.ch";
|
|
||||||
export const LOCAL_ENDORSER_API_SERVER = "http://127.0.0.1:3000";
|
|
||||||
export const LOCAL_ENDORSER_VIEW_SERVER = "http://127.0.0.1:3001";
|
|
||||||
export const TEST_ENDORSER_API_SERVER = "https://test.endorser.ch:8000";
|
|
||||||
export const TEST_ENDORSER_VIEW_SERVER = "https://test.endorser.ch:8080";
|
|
||||||
|
|
||||||
// for contents set in reducers
|
|
||||||
interface Payload<T> {
|
|
||||||
type: string;
|
|
||||||
payload: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LogMsg {
|
|
||||||
log: boolean;
|
|
||||||
msg: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const appSlice = createSlice({
|
|
||||||
name: "app",
|
|
||||||
initialState: {
|
|
||||||
// This is nullable because it is cached state from the DB...
|
|
||||||
// it'll be null if we haven't even loaded from the DB yet.
|
|
||||||
settings: null as Settings,
|
|
||||||
|
|
||||||
// This is nullable because it is cached state from the DB...
|
|
||||||
// it'll be null if we haven't even loaded from the DB yet.
|
|
||||||
identifiers: null as Array<IIdentifier> | null,
|
|
||||||
|
|
||||||
// This is nullable because it is cached state from the DB...
|
|
||||||
// it'll be null if we haven't even loaded from the DB yet.
|
|
||||||
contacts: null as Array<Contact> | null,
|
|
||||||
|
|
||||||
viewServer: DEFAULT_ENDORSER_VIEW_SERVER,
|
|
||||||
|
|
||||||
logMessage: "",
|
|
||||||
|
|
||||||
advancedMode: false,
|
|
||||||
testMode: false,
|
|
||||||
},
|
|
||||||
reducers: {
|
|
||||||
addIdentifier: (state, contents: Payload<IIdentifier>) => {
|
|
||||||
state.identifiers = state.identifiers.concat([contents.payload]);
|
|
||||||
},
|
|
||||||
addLog: (state, contents: Payload<LogMsg>) => {
|
|
||||||
if (state.logMessage.length > MAX_LOG_LENGTH) {
|
|
||||||
state.logMessage =
|
|
||||||
"<truncated>\n..." +
|
|
||||||
state.logMessage.substring(
|
|
||||||
state.logMessage.length - MAX_LOG_LENGTH / 2
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (contents.payload.log) {
|
|
||||||
console.log(contents.payload.msg);
|
|
||||||
state.logMessage += "\n" + contents.payload.msg;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setAdvancedMode: (state, contents: Payload<boolean>) => {
|
|
||||||
state.advancedMode = contents.payload;
|
|
||||||
},
|
|
||||||
setContacts: (state, contents: Payload<Array<Contact>>) => {
|
|
||||||
state.contacts = contents.payload;
|
|
||||||
},
|
|
||||||
setContact: (state, contents: Payload<Contact>) => {
|
|
||||||
const index = R.findIndex(
|
|
||||||
(c) => c.did === contents.payload.did,
|
|
||||||
state.contacts
|
|
||||||
);
|
|
||||||
state.contacts[index] = contents.payload;
|
|
||||||
},
|
|
||||||
setHomeScreen: (state, contents: Payload<string>) => {
|
|
||||||
state.settings.homeScreen = contents.payload;
|
|
||||||
},
|
|
||||||
setIdentifiers: (state, contents: Payload<Array<IIdentifier>>) => {
|
|
||||||
state.identifiers = contents.payload;
|
|
||||||
},
|
|
||||||
setSettings: (state, contents: Payload<Settings>) => {
|
|
||||||
state.settings = contents.payload;
|
|
||||||
},
|
|
||||||
setTestMode: (state, contents: Payload<boolean>) => {
|
|
||||||
state.testMode = contents.payload;
|
|
||||||
},
|
|
||||||
setViewServer: (state, contents: Payload<string>) => {
|
|
||||||
state.viewServer = contents.payload;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const appStore = configureStore({ reducer: appSlice.reducer });
|
|
||||||
*/
|
|
||||||
Reference in New Issue
Block a user