feat: guesstimate platform, show guesstimate viz on question pages
This commit is contained in:
parent
05b0daa631
commit
5c248388b6
103
src/backend/platforms/guesstimate.ts
Normal file
103
src/backend/platforms/guesstimate.ts
Normal file
|
@ -0,0 +1,103 @@
|
|||
import axios from "axios";
|
||||
import { parseISO } from "date-fns";
|
||||
|
||||
/* Imports */
|
||||
import { Question } from "@prisma/client";
|
||||
|
||||
import { AlgoliaQuestion } from "../../backend/utils/algolia";
|
||||
import { prisma } from "../database/prisma";
|
||||
import { Platform } from "./";
|
||||
|
||||
/* Definitions */
|
||||
const searchEndpoint =
|
||||
"https://m629r9ugsg-dsn.algolia.net/1/indexes/Space_production/query?x-algolia-agent=Algolia%20for%20vanilla%20JavaScript%203.32.1&x-algolia-application-id=M629R9UGSG&x-algolia-api-key=4e893740a2bd467a96c8bfcf95b2809c";
|
||||
|
||||
const apiEndpoint = "https://guesstimate.herokuapp.com";
|
||||
|
||||
/* Body */
|
||||
|
||||
const modelToQuestion = (model: any): Question => {
|
||||
const { description } = model;
|
||||
// const description = model.description
|
||||
// ? model.description.replace(/\n/g, " ").replace(/ /g, " ")
|
||||
// : "";
|
||||
const stars = description.length > 250 ? 2 : 1;
|
||||
const timestamp = parseISO(model.created_at);
|
||||
const q: Question = {
|
||||
id: `guesstimate-${model.id}`,
|
||||
title: model.name,
|
||||
url: `https://www.getguesstimate.com/models/${model.id}`,
|
||||
timestamp,
|
||||
platform: "guesstimate",
|
||||
description,
|
||||
options: [],
|
||||
qualityindicators: {
|
||||
stars,
|
||||
numforecasts: 1,
|
||||
numforecasters: 1,
|
||||
},
|
||||
extra: {
|
||||
visualization: model.big_screenshot,
|
||||
},
|
||||
// ranking: 10 * (index + 1) - 0.5, //(model._rankingInfo - 1*index)// hack
|
||||
};
|
||||
return q;
|
||||
};
|
||||
|
||||
async function search(query: string): Promise<AlgoliaQuestion[]> {
|
||||
const response = await axios({
|
||||
url: searchEndpoint,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data: `{\"params\":\"query=${query.replace(
|
||||
/ /g,
|
||||
"%20"
|
||||
)}&hitsPerPage=20&page=0&getRankingInfo=true\"}`,
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
const models: any[] = response.data.hits;
|
||||
const mappedModels: AlgoliaQuestion[] = models.map((model) => {
|
||||
const q = modelToQuestion(model);
|
||||
return {
|
||||
...q,
|
||||
timestamp: String(q.timestamp),
|
||||
};
|
||||
});
|
||||
|
||||
// filter for duplicates. Surprisingly common.
|
||||
let uniqueTitles = [];
|
||||
let uniqueModels: AlgoliaQuestion[] = [];
|
||||
for (let model of mappedModels) {
|
||||
if (!uniqueTitles.includes(model.title) && !model.title.includes("copy")) {
|
||||
uniqueModels.push(model);
|
||||
uniqueTitles.push(model.title);
|
||||
}
|
||||
}
|
||||
|
||||
return uniqueModels;
|
||||
}
|
||||
|
||||
const fetchQuestion = async (id: number): Promise<Question> => {
|
||||
const response = await axios({ url: `${apiEndpoint}/spaces/${id}` });
|
||||
let q = modelToQuestion(response.data);
|
||||
q = await prisma.question.upsert({
|
||||
where: { id: q.id },
|
||||
create: q,
|
||||
update: q,
|
||||
});
|
||||
return q;
|
||||
};
|
||||
|
||||
export const guesstimate: Platform & {
|
||||
search: typeof search;
|
||||
fetchQuestion: typeof fetchQuestion;
|
||||
} = {
|
||||
name: "guesstimate",
|
||||
label: "Guesstimate",
|
||||
color: "#223900",
|
||||
search,
|
||||
fetchQuestion,
|
||||
};
|
|
@ -7,6 +7,7 @@ import { foretold } from "./foretold";
|
|||
import { givewellopenphil } from "./givewellopenphil";
|
||||
import { goodjudgment } from "./goodjudgment";
|
||||
import { goodjudgmentopen } from "./goodjudgmentopen";
|
||||
import { guesstimate } from "./guesstimate";
|
||||
import { infer } from "./infer";
|
||||
import { kalshi } from "./kalshi";
|
||||
import { manifold } from "./manifold";
|
||||
|
@ -72,6 +73,7 @@ export const platforms: Platform[] = [
|
|||
givewellopenphil,
|
||||
goodjudgment,
|
||||
goodjudgmentopen,
|
||||
guesstimate,
|
||||
infer,
|
||||
kalshi,
|
||||
manifold,
|
||||
|
@ -161,21 +163,12 @@ export interface PlatformConfig {
|
|||
}
|
||||
|
||||
// get frontend-safe version of platforms data
|
||||
export const getPlatformsConfig = (options: {
|
||||
withGuesstimate: boolean;
|
||||
}): PlatformConfig[] => {
|
||||
export const getPlatformsConfig = (): PlatformConfig[] => {
|
||||
const platformsConfig = platforms.map((platform) => ({
|
||||
name: platform.name,
|
||||
label: platform.label,
|
||||
color: platform.color,
|
||||
}));
|
||||
if (options.withGuesstimate) {
|
||||
platformsConfig.push({
|
||||
name: "guesstimate",
|
||||
label: "Guesstimate",
|
||||
color: "223900",
|
||||
});
|
||||
}
|
||||
|
||||
return platformsConfig;
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ import { History, Question } from "@prisma/client";
|
|||
|
||||
import { prisma } from "../../backend/database/prisma";
|
||||
import { QualityIndicators } from "../../backend/platforms";
|
||||
import { guesstimate } from "../../backend/platforms/guesstimate";
|
||||
import { builder } from "../builder";
|
||||
import { PlatformObj } from "./platforms";
|
||||
|
||||
|
@ -144,6 +145,13 @@ builder.queryField("question", (t) =>
|
|||
id: t.arg({ type: "ID", required: true }),
|
||||
},
|
||||
resolve: async (parent, args) => {
|
||||
const parts = String(args.id).split("-");
|
||||
const [platform, id] = [parts[0], parts.slice(1).join("-")];
|
||||
if (platform === "guesstimate") {
|
||||
const q = await guesstimate.fetchQuestion(Number(id));
|
||||
console.log(q);
|
||||
return q;
|
||||
}
|
||||
return await prisma.question.findUnique({
|
||||
where: {
|
||||
id: String(args.id),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { guesstimate } from "../../backend/platforms/guesstimate";
|
||||
import { AlgoliaQuestion } from "../../backend/utils/algolia";
|
||||
import searchGuesstimate from "../../web/worker/searchGuesstimate";
|
||||
import searchWithAlgolia from "../../web/worker/searchWithAlgolia";
|
||||
import { builder } from "../builder";
|
||||
import { QuestionObj } from "./questions";
|
||||
|
@ -54,7 +54,7 @@ builder.queryField("searchQuestions", (t) =>
|
|||
const [responsesNotGuesstimate, responsesGuesstimate] =
|
||||
await Promise.all([
|
||||
unawaitedAlgoliaResponse,
|
||||
searchGuesstimate(query),
|
||||
guesstimate.search(query),
|
||||
]); // faster than two separate requests
|
||||
results = [...responsesNotGuesstimate, ...responsesGuesstimate];
|
||||
} else {
|
||||
|
|
|
@ -13,7 +13,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
|
|||
const [ssrCache, client] = ssrUrql();
|
||||
const urlQuery = context.query;
|
||||
|
||||
const platformsConfig = getPlatformsConfig({ withGuesstimate: true });
|
||||
const platformsConfig = getPlatformsConfig();
|
||||
|
||||
const defaultQueryParameters: QueryParameters = {
|
||||
query: "",
|
||||
|
|
|
@ -74,7 +74,17 @@ const LargeQuestionCard: React.FC<{
|
|||
</div>
|
||||
|
||||
<div className="mb-8">
|
||||
{question.platform.id === "guesstimate" ? (
|
||||
<a className="no-underline" href={question.url} target="_blank">
|
||||
<img
|
||||
className="rounded-sm"
|
||||
src={question.visualization}
|
||||
alt="Guesstimate Screenshot"
|
||||
/>
|
||||
</a>
|
||||
) : (
|
||||
<HistoryChart question={question} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ReactMarkdown
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/* Imports */
|
||||
import axios from "axios";
|
||||
|
||||
import { AlgoliaQuestion } from "../../backend/utils/algolia";
|
||||
|
||||
/* Definitions */
|
||||
const urlEndPoint =
|
||||
"https://m629r9ugsg-dsn.algolia.net/1/indexes/Space_production/query?x-algolia-agent=Algolia%20for%20vanilla%20JavaScript%203.32.1&x-algolia-application-id=M629R9UGSG&x-algolia-api-key=4e893740a2bd467a96c8bfcf95b2809c";
|
||||
|
||||
/* Body */
|
||||
|
||||
export default async function searchGuesstimate(
|
||||
query
|
||||
): Promise<AlgoliaQuestion[]> {
|
||||
const response = await axios({
|
||||
url: urlEndPoint,
|
||||
// credentials: "omit",
|
||||
headers: {
|
||||
// "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0",
|
||||
Accept: "application/json",
|
||||
"Accept-Language": "en-US,en;q=0.5",
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data: `{\"params\":\"query=${query.replace(
|
||||
/ /g,
|
||||
"%20"
|
||||
)}&hitsPerPage=20&page=0&getRankingInfo=true\"}`,
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
const models: any[] = response.data.hits;
|
||||
const mappedModels: AlgoliaQuestion[] = models.map((model, index) => {
|
||||
const description = model.description
|
||||
? model.description.replace(/\n/g, " ").replace(/ /g, " ")
|
||||
: "";
|
||||
const stars = description.length > 250 ? 2 : 1;
|
||||
const q: AlgoliaQuestion = {
|
||||
id: `guesstimate-${model.id}`,
|
||||
title: model.name,
|
||||
url: `https://www.getguesstimate.com/models/${model.id}`,
|
||||
timestamp: model.created_at, // TODO - check that format matches
|
||||
platform: "guesstimate",
|
||||
description,
|
||||
options: [],
|
||||
qualityindicators: {
|
||||
stars,
|
||||
numforecasts: 1,
|
||||
numforecasters: 1,
|
||||
},
|
||||
extra: {
|
||||
visualization: model.big_screenshot,
|
||||
},
|
||||
// ranking: 10 * (index + 1) - 0.5, //(model._rankingInfo - 1*index)// hack
|
||||
};
|
||||
return q;
|
||||
});
|
||||
|
||||
// filter for duplicates. Surprisingly common.
|
||||
let uniqueTitles = [];
|
||||
let uniqueModels: AlgoliaQuestion[] = [];
|
||||
for (let model of mappedModels) {
|
||||
if (!uniqueTitles.includes(model.title) && !model.title.includes("copy")) {
|
||||
uniqueModels.push(model);
|
||||
uniqueTitles.push(model.title);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(uniqueModels);
|
||||
return uniqueModels;
|
||||
}
|
||||
|
||||
// searchGuesstimate("COVID-19").then(guesstimateModels => console.log(guesstimateModels))
|
Loading…
Reference in New Issue
Block a user