Public
HTTP (deprecated)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

Homeless Services by OurTechnology

Homeless Services by OurTechnology

At OurTechnology, we create technology solutions to empower and equip those who serve the homeless. We have a large data set of available resources in the US to aid in helping those experiencing homelessness find local resources, community, and support.

This private (but public to read) API is used in our ChatGPT Assistant, Homeless Services.

  • OpenAI announced on May 13, 2024 that free users will soon be able to "discover and use GPTs and the GPT Store (OpenAI)"
  • There's a larger number of people experiencing homelessness who own a phone than what I imagined.
  • ChatGPT allows for a simple interface, even with voice chat (a more natural way to navigate the tool), to find resources to help those experiencing homelessness. And, it's fast!

Technical details

  • The data set has been compiled together over the years and will continue to be updated as new techniques and partnerships make that possible.
  • We use Typesense, a search as a service tool, to provide lightning fast search results for homeless resources near you.
  • This endpoint is created with Hono and is an incredibly easy way to create an API.

Contact OurTechnology

While this is on Cameron Pak's ValTown, this code is owned and operated by OurTechnology.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { bearerAuth } from "npm:hono/bearer-auth";
import { cors } from "npm:hono/cors";
import { Hono } from "npm:hono@3";
import Typesense from "npm:typesense";
import type { SearchParams, SearchParamsWithPreset, SearchResponseHit } from "npm:typesense/lib/Typesense/Documents";
const MAX_SEARCH_RADIUS_IN_MILES = 10;
const COLLECTIONS = {
"resources": "resources",
};
const typesenseClient = new Typesense.Client({
"nodes": [{
"host": Deno.env.get("TYPESENSE_HOST") || "", // For Typesense Cloud use xxx.a1.typesense.net
"port": 443, // For Typesense Cloud use 443
"protocol": "https", // For Typesense Cloud use https
}],
"apiKey": Deno.env.get("TYPESENSE_API_KEY") || "",
"connectionTimeoutSeconds": 10,
"retryIntervalSeconds": 0.1,
"healthcheckIntervalSeconds": 2,
"logLevel": "debug",
});
interface Resource {
id: string;
name: string;
address: {
full_address: string;
latitude: number;
longitude: number;
};
website: string;
phone: string;
user_email: string;
description: string;
utc_offset: number;
featured_image_url: string;
hours_text: string | null;
hours: {
day: string;
day_int: number;
open_time: string | null;
close_time: string | null;
}[];
services: {
id: string | number;
name: string;
description: string;
category: {
icon: string;
name: ResourceTypes;
};
}[];
qualifications: {
id: string | number;
name: string;
}[];
// Custom field added by Cameron Pak to calculate on the fly.
distance_between: number;
}
const CATEGORY_IDS_FROM_TYPESENSE = {
// Favorites does not exist in Typesense but is a ResourceTypes type.
"Favorites": -1,
"Food": 53,
"Shelter": 52,
"Churches": 56,
"Resources": 57,
"Medical": 54,
"Addiction Recovery": 58,
"Domestic Violence": 51,
"Housing": 69,
};
type ResourceTypes = keyof typeof CATEGORY_IDS_FROM_TYPESENSE;
/**
* Converts meters to miles.
*
* @param {number} meters - the distance in meters to convert
* @return {number} the distance in miles
*/
function convertMetersToMiles(meters: number): number {
return 0.000621371 * meters;
}
// Round a number to the nearest quarter.
function roundToQuarter(number: number) {
let remainder = number % 1;
// I only want 1/8th of a mile to appear when when that's the only remainder.
if (number < 1 && remainder <= 0.125) {
return Math.floor(number) + 0.125;
} else if (remainder <= 0.375) {
return Math.floor(number) + 0.25;
} else if (remainder <= 0.625) {
return Math.floor(number) + 0.50;
} else if (remainder <= 0.875) {
return Math.floor(number) + 0.75;
} else {
cameronpak-homeless.web.val.run
May 24, 2024