diff --git a/docs/asset-manifest.json b/docs/asset-manifest.json index a9f84f4aa5..f554e44654 100644 --- a/docs/asset-manifest.json +++ b/docs/asset-manifest.json @@ -1,13 +1,13 @@ { "files": { - "main.css": "/static/css/main.7c29d878.css", - "main.js": "/static/js/main.0a629ee5.js", + "main.css": "/static/css/main.87b17666.css", + "main.js": "/static/js/main.7083016d.js", "index.html": "/index.html", - "main.7c29d878.css.map": "/static/css/main.7c29d878.css.map", - "main.0a629ee5.js.map": "/static/js/main.0a629ee5.js.map" + "main.87b17666.css.map": "/static/css/main.87b17666.css.map", + "main.7083016d.js.map": "/static/js/main.7083016d.js.map" }, "entrypoints": [ - "static/css/main.7c29d878.css", - "static/js/main.0a629ee5.js" + "static/css/main.87b17666.css", + "static/js/main.7083016d.js" ] } \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 5503710c9b..501b66037e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1 +1 @@ -
a||125d?(a.sortIndex=c,f(t,a),null===h(r)&&a===h(t)&&(B?(E(L),L=-1):B=!0,K(H,c-d))):(a.sortIndex=e,f(r,a),A||z||(A=!0,I(J)));return a};\nexports.unstable_shouldYield=M;exports.unstable_wrapCallback=function(a){var b=y;return function(){var c=y;y=b;try{return a.apply(this,arguments)}finally{y=c}}};\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/scheduler.production.min.js');\n} else {\n module.exports = require('./cjs/scheduler.development.js');\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","export const SCORE = 'score'\nexport const DATE = 'date'\nexport const ASCE = 'ascending'\nexport const DESC = 'descending'\nexport const CURRENT_YEAR = (new Date()).getFullYear()\nexport const MIN_YEAR = 2018\n\nexport const ABSTRACT_URL = process.env.REACT_APP_ABSTRACT_URL\nexport const API_HOST = process.env.REACT_APP_API_HOST\nexport const LAST_UPDATE = \"last update Dec. 01, 2024\"\nexport const CITATION = \"@misc{kim2024cspapers, title={cspapers.org}, url={https://cspapers.org/}, author={Kim, Sungwoo}, year={2024}, month=aug, language={en} }\"","import { ABSTRACT_URL, API_HOST } from \"./const\";\n\n/**\n * See api.cspapers.org/types/types.go\n * @typedef {{\n * query: string,\n * orderBy: string,\n * ascending: bool,\n * yearFrom: number,\n * yearTo: number,\n * skip: number,\n * must: string[]\n * }} SearchRequest\n * \n * @typedef {{\n * total: number,\n * skip: number,\n * duration: number, // msec, spent on searching\n * data: [SearchResponseUnit],\n * }} SearchResponse\n * \n * @typedef {{\n * title: string,\n * year: number,\n * venue: string,\n * index: string,\n * score: number,\n * }} SearchResponseUnit\n * \n */\n\n\n/**\n * \n * @param {SearchRequest} req \n * @returns {[SearchResponse, Error | null ]}\n */\nlet lastlyCalledAt = 0;\n/*\nUse compare-and-exchange to avoid data race.\nMake search() return the result of the latest fetch() *request*.\nOtherwise, the user will see the latest fetch() *response*, that could\nbe stale and does not match to the current query.\n*/\nconst search = async (req) => {\n const calledAt = Date.now()\n try {\n lastlyCalledAt = calledAt\n const res = await fetch(API_HOST + marshal(req), { signal: AbortSignal.timeout(5_000) })\n if (!res.ok) {\n throw new Error(`Response status: ${res.status}`);\n }\n const json = await res.json();\n if (json === null) {\n throw new Error(`response data is null`);\n }\n\n /* mimicking atomic compare-and-swap */\n const lastlyCalledAtAfterFetch = lastlyCalledAt\n lastlyCalledAt = calledAt === lastlyCalledAt ? 0 : lastlyCalledAt\n /* mimicking atomic compare-and-swap */\n\n if (lastlyCalledAtAfterFetch === calledAt) {\n /* this context is the latest */\n return [json, false]\n } else {\n return [{}, new Error(`Later call exists`)]\n }\n } catch (error) {\n /* mimicking atomic compare-and-swap */\n const lastlyCalledAtAfterFetch = lastlyCalledAt\n lastlyCalledAt = calledAt === lastlyCalledAt ? 0 : lastlyCalledAt\n /* mimicking atomic compare-and-swap */\n\n if (lastlyCalledAtAfterFetch === calledAt) {\n /* this context is the latest */\n return [{}, new Error('timeout')]\n } else {\n console.error(error)\n return [{}, error]\n }\n }\n}\n\n/**\n * Convert SearchRequest to a query string\n * @param {SearchRequest} req \n * @returns {string} QueryString\n */\nconst marshal = (req) => {\n const q = new URLSearchParams(req)\n return `/?${q.toString()}`\n}\n\n/**\n * \n * @param {number} year\n * @param {string} venue \n * @param {string} title \n * @returns {[string, Error | null ]} abstract\n */\nconst getAbstract = async (year, venue, title) => {\n try {\n const res = await fetch(`${ABSTRACT_URL}/${year}/${venue.toLowerCase()}/${title}`)\n if (res.status === 404) {\n return [\"\", null]\n } else if (!res.ok) {\n return [\"\", new Error(`${res.status} ${res.statusText}`)]\n }\n const text = await res.text()\n return [text, null]\n } catch (err) {\n return [\"\", err]\n }\n}\n\nexport {\n getAbstract, search\n};\n","export const seq = (start, end, step = 1) => Array.from({ length: end - start }, (_, i) => start + i * step)\nexport const isEven = n => n % 2 === 0\n\nexport const fst = ([a, _]) => a\nexport const snd = ([_, a]) => a\n\n/**\n * Build tree from edges.\n * @typedef {{ name: string, children: [Tree] }} Tree\n * @typedef { [ parent: string, child: string ]} Edge\n * @param {[Edge]} edges\n * @param {string} root\n * @returns {Tree}\n */\nexport const buildTree = (edges, root) => {\n const [adjacent, notAdjacent] = edges.reduce(\n (acc, cur) => fst(cur) === root ?\n [[...fst(acc), cur], snd(acc)] :\n [fst(acc), [...snd(acc), cur]],\n [[], []])\n\n const t = buildTree1Depth(adjacent, root)\n if (t.children.length === 0) {\n return { name: root }\n }\n t.children = t.children.map(tre => buildTree(notAdjacent, tre.name))\n return t\n}\n\nexport const doubleQuotes = (str = \"\") =>\n str.split('\"').slice(0, -1).filter((_, idx) => idx % 2 === 1)\n\nconst buildTree1Depth = (edges = [], parent = \"\") => ({\n name: parent,\n children: edges.reduce((acc, cur) => fst(cur) === parent ? [...acc, { name: snd(cur) }] : acc, [])\n})","import { buildTree } from \"./functional\"\n\n/* add new conferences here */\nconst edges = [\n [\"All Areas\", \"AI\"],\n\n [\"AI\", \"Artificial intelligence\"],\n [\"Artificial intelligence\", \"AAAI\"],\n [\"Artificial intelligence\", \"IJCAI\"],\n\n [\"AI\", \"Computer vision\"],\n [\"Computer vision\", \"CVPR\"],\n [\"Computer vision\", \"ICCV\"],\n [\"Computer vision\", \"ECCV\"],\n\n [\"AI\", \"Data mining\"],\n [\"Data mining\", \"KDD\"],\n [\"Data mining\", \"CIKM\"],\n [\"Data mining\", \"ICDM\"],\n\n [\"AI\", \"Machine learning\"],\n [\"Machine learning\", \"ICLR\"],\n [\"Machine learning\", \"ICML\"],\n [\"Machine learning\", \"NeurIPS\"],\n\n [\"AI\", \"Natural language processing\"],\n [\"Natural language processing\", \"ACL\"],\n [\"Natural language processing\", \"EMNLP\"],\n [\"Natural language processing\", \"NAACL\"],\n\n [\"AI\", \"The Web & information retrieval\"],\n [\"The Web & information retrieval\", \"SIGIR\"],\n [\"The Web & information retrieval\", \"WWW\"],\n\n [\"All Areas\", \"Systems\"],\n\n [\"Systems\", \"Computer architecture\"],\n [\"Computer architecture\", \"ASPLOS\"],\n [\"Computer architecture\", \"ISCA\"],\n [\"Computer architecture\", \"MICRO\"],\n [\"Computer architecture\", \"HPCA\"],\n\n [\"Systems\", \"Computer network\"],\n [\"Computer network\", \"SIGCOMM\"],\n [\"Computer network\", \"NSDI\"],\n\n [\"Systems\", \"Computer security\"],\n [\"Computer security\", \"NDSS\"],\n [\"Computer security\", \"Usenix\"],\n [\"Computer security\", \"SP\"],\n [\"Computer security\", \"CCS\"],\n\n [\"Systems\", \"Computer security 2\"],\n [\"Computer security 2\", \"ACSAC\"],\n [\"Computer security 2\", \"ASIACCS\"],\n [\"Computer security 2\", \"EUROSP\"],\n\n [\"Systems\", \"Databases\"],\n [\"Databases\", \"SIGMOD\"],\n [\"Databases\", \"VLDB\"],\n\n [\"Systems\", \"Design automation\"],\n [\"Design automation\", \"DAC\"],\n [\"Design automation\", \"ICCAD\"],\n\n [\"Systems\", \"High-performance computing\"],\n [\"High-performance computing\", \"HPDC\"],\n [\"High-performance computing\", \"ICS\"],\n [\"High-performance computing\", \"SC\"],\n\n [\"Systems\", \"Measurement & perf. analysis\"],\n [\"Measurement & perf. analysis\", \"IMC\"],\n [\"Measurement & perf. analysis\", \"SIGMETRICS\"],\n\n [\"Systems\", \"Embedded & real-time systems\"],\n [\"Embedded & real-time systems\", \"EMSOFT\"],\n [\"Embedded & real-time systems\", \"RTAS\"],\n [\"Embedded & real-time systems\", \"RTSS\"],\n\n [\"Systems\", \"Mobile computing\"],\n [\"Mobile computing\", \"MobiCom\"],\n [\"Mobile computing\", \"MobiSys\"],\n [\"Mobile computing\", \"SenSys\"],\n\n [\"Systems\", \"Operating systems\"],\n [\"Operating systems\", \"OSDI\"],\n [\"Operating systems\", \"SOSP\"],\n [\"Operating systems\", \"ATC\"],\n [\"Operating systems\", \"EuroSYS\"],\n\n [\"Systems\", \"Software engineering\"],\n [\"Software engineering\", \"FSE\"],\n [\"Software engineering\", \"ICSE\"],\n [\"Software engineering\", \"ASE\"],\n [\"Software engineering\", \"ISSTA\"],\n\n [\"Systems\", \"Programming languages\"],\n [\"Programming languages\", \"PACMPL\"],\n [\"Programming languages\", \"PLDI\"],\n\n [\"All Areas\", \"Theory\"],\n\n [\"Theory\", \"Algorithms & complexity\"],\n [\"Algorithms & complexity\", \"FOCS\"],\n [\"Algorithms & complexity\", \"SODA\"],\n [\"Algorithms & complexity\", \"STOC\"],\n\n [\"Theory\", \"Cryptography\"],\n [\"Cryptography\", \"CRYPTO\"],\n [\"Cryptography\", \"EuroCrypt\"],\n\n [\"Theory\", \"Logic & verification\"],\n [\"Logic & verification\", \"LICS\"],\n\n [\"All Areas\", \"Interdisciplinary Areas\"],\n\n [\"Interdisciplinary Areas\", \"Computer science education\"],\n [\"Computer science education\", \"SIGCSE\"],\n\n [\"Interdisciplinary Areas\", \"Economics & computation\"],\n [\"Economics & computation\", \"EC\"],\n [\"Economics & computation\", \"WINE\"],\n \n [\"Interdisciplinary Areas\", \"Human-computer interaction\"],\n [\"Human-computer interaction\", \"CHI\"],\n [\"Human-computer interaction\", \"UbiComp\"],\n [\"Human-computer interaction\", \"UIST\"],\n\n [\"Interdisciplinary Areas\", \"Robotics\"],\n [\"Robotics\", \"ICRA\"],\n [\"Robotics\", \"IROS\"],\n [\"Robotics\", \"RSS\"],\n]\n\nconst comments = {\n \"ACL\": \"(long)\",\n \"PLDI\": \"(2018 - 2022)\",\n \"SOSP\": \"(2017 - 2023), biyearly\",\n}\n\n/**\n * Return leaves's names.\n * @typedef {{ name: string, children: [Tree] }} Tree\n * @param {Tree} tree\n * @returns {string}\n */\nconst flatten = (tree) =>\n tree.children.reduce((acc, cur) =>\n cur.children ? [...acc, ...flatten(cur)] : [...acc, cur.name]\n , [])\n\nconst conferences = {\n tree: buildTree(edges, \"All Areas\"),\n flatten,\n}\n\nexport {\n conferences,\n comments\n}","const startsWithLower = (text = \"\", tok = \"\") =>\n text.toLowerCase().startsWith(tok.toLowerCase())\n\nconst consume = (text = \"\", tok = \"\") =>\n startsWithLower(text, tok) ? \n text.substring(tok.length) :\n text\n\nconst split = (text = \"\", sep = []) => {\n if (sep.length === 0) {\n return []\n }\n const ret = []\n /* match long word first */\n sep = sep.sort((a, b) => b.length - a.length)\n \n let word = \"\"\n while (text.length !== 0) {\n let tok = \"\"\n for(tok of sep) {\n if (startsWithLower(text, tok)) {\n break\n }\n tok = \"\"\n }\n if (tok === \"\") {\n word += text.charAt(0)\n text = text.substring(1)\n } else {\n if (word !== \"\") {\n ret.push(word)\n word = \"\"\n }\n if (ret.length === 0) {\n ret.push(\"\")\n }\n ret.push(text.substring(0, tok.length))\n text = consume(text, tok)\n }\n }\n if (word !== \"\") {\n ret.push(word)\n word = \"\"\n }\n return ret\n}\n\n/**\n * \n * @param {{ text: string, highlight: string[] }} props\n * @returns \n */\nfunction Highlight(props) {\n if (props.highlight.length === 0) {\n return props.text\n }\n const parts = split(props.text, props.highlight);\n return parts.map((part, index) =>\n index % 2 === 1 ? (\n \n {part}\n \n ) : (\n part\n )\n );\n}\n\n\nexport default Highlight;\n","import { useState } from 'react';\nimport { getAbstract } from '../api';\nimport Highlight from './Highlight'\n\n/**\n * \n * @param {{ year: number, venue: string, title: string, highlight: string[] }} props\n * @returns \n */\nfunction Paper(props) {\n const [collapsed, setCollapsed] = useState(true)\n const [abstract, setAbstract] = useState('')\n const [isAbsLoaded, setIsAbsLoaded] = useState(false)\n const venueUpper = props.venue.toUpperCase()\n\n const toggleCollapsed = () => {\n const nextCollapsed = !collapsed\n setCollapsed(nextCollapsed)\n if (nextCollapsed) {\n return\n }\n if (isAbsLoaded) {\n return\n }\n getAbstract(props.year, props.venue, props.title)\n .then(([abs, err]) => {\n if (err) {\n setAbstract(\"failed to retreive an abstract: \", err)\n } else {\n setAbstract(abs)\n }\n setIsAbsLoaded(true)\n })\n }\n\n return (\n a||125d?(a.sortIndex=c,f(t,a),null===h(r)&&a===h(t)&&(B?(E(L),L=-1):B=!0,K(H,c-d))):(a.sortIndex=e,f(r,a),A||z||(A=!0,I(J)));return a};\nexports.unstable_shouldYield=M;exports.unstable_wrapCallback=function(a){var b=y;return function(){var c=y;y=b;try{return a.apply(this,arguments)}finally{y=c}}};\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/scheduler.production.min.js');\n} else {\n module.exports = require('./cjs/scheduler.development.js');\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","export const SCORE = 'score'\nexport const DATE = 'date'\nexport const ASCE = 'ascending'\nexport const DESC = 'descending'\nexport const CURRENT_YEAR = (new Date()).getFullYear()\nexport const MIN_YEAR = 2018\n\nexport const ABSTRACT_URL = process.env.REACT_APP_ABSTRACT_URL\nexport const API_HOST = process.env.REACT_APP_API_HOST\nexport const LAST_UPDATE = \"last update Dec. 01, 2024\"\nexport const CITATION = \"@misc{kim2024cspapers, title={cspapers.org}, url={https://cspapers.org/}, author={Kim, Sungwoo}, year={2024}, month=aug, language={en} }\"","import { ABSTRACT_URL, API_HOST } from \"./const\";\n\n/**\n * See api.cspapers.org/types/types.go\n * @typedef {{\n * query: string,\n * orderBy: string,\n * ascending: bool,\n * yearFrom: number,\n * yearTo: number,\n * skip: number,\n * must: string[]\n * }} SearchRequest\n * \n * @typedef {{\n * total: number,\n * skip: number,\n * duration: number, // msec, spent on searching\n * data: [SearchResponseUnit],\n * }} SearchResponse\n * \n * @typedef {{\n * title: string,\n * year: number,\n * venue: string,\n * index: string,\n * score: number,\n * }} SearchResponseUnit\n * \n */\n\n\n/**\n * \n * @param {SearchRequest} req \n * @returns {[SearchResponse, Error | null ]}\n */\nlet lastlyCalledAt = 0;\n/*\nUse compare-and-exchange to avoid data race.\nMake search() return the result of the latest fetch() *request*.\nOtherwise, the user will see the latest fetch() *response*, that could\nbe stale and does not match to the current query.\n*/\nconst search = async (req) => {\n const calledAt = Date.now()\n try {\n lastlyCalledAt = calledAt\n const res = await fetch(API_HOST + marshal(req), { signal: AbortSignal.timeout(5_000) })\n if (!res.ok) {\n throw new Error(`Response status: ${res.status}`);\n }\n const json = await res.json();\n if (json === null) {\n throw new Error(`response data is null`);\n }\n\n /* mimicking atomic compare-and-swap */\n const lastlyCalledAtAfterFetch = lastlyCalledAt\n lastlyCalledAt = calledAt === lastlyCalledAt ? 0 : lastlyCalledAt\n /* mimicking atomic compare-and-swap */\n\n if (lastlyCalledAtAfterFetch === calledAt) {\n /* this context is the latest */\n return [json, false]\n } else {\n return [{}, new Error(`Later call exists`)]\n }\n } catch (error) {\n /* mimicking atomic compare-and-swap */\n const lastlyCalledAtAfterFetch = lastlyCalledAt\n lastlyCalledAt = calledAt === lastlyCalledAt ? 0 : lastlyCalledAt\n /* mimicking atomic compare-and-swap */\n\n if (lastlyCalledAtAfterFetch === calledAt) {\n /* this context is the latest */\n return [{}, new Error('timeout')]\n } else {\n console.error(error)\n return [{}, error]\n }\n }\n}\n\n/**\n * Convert SearchRequest to a query string\n * @param {SearchRequest} req \n * @returns {string} QueryString\n */\nconst marshal = (req) => {\n const q = new URLSearchParams(req)\n return `/?${q.toString()}`\n}\n\n/**\n * \n * @param {number} year\n * @param {string} venue \n * @param {string} title \n * @returns {[string, Error | null ]} abstract\n */\nconst getAbstract = async (year, venue, title) => {\n try {\n const res = await fetch(`${ABSTRACT_URL}/${year}/${venue.toLowerCase()}/${title}`)\n if (res.status === 404) {\n return [\"\", null]\n } else if (!res.ok) {\n return [\"\", new Error(`${res.status} ${res.statusText}`)]\n }\n const text = await res.text()\n return [text, null]\n } catch (err) {\n return [\"\", err]\n }\n}\n\nexport {\n getAbstract, search\n};\n","export const seq = (start, end, step = 1) => Array.from({ length: end - start }, (_, i) => start + i * step)\nexport const isEven = n => n % 2 === 0\n\nexport const fst = ([a, _]) => a\nexport const snd = ([_, a]) => a\n\n/**\n * Build tree from edges.\n * @typedef {{ name: string, children: [Tree] }} Tree\n * @typedef { [ parent: string, child: string ]} Edge\n * @param {[Edge]} edges\n * @param {string} root\n * @returns {Tree}\n */\nexport const buildTree = (edges, root) => {\n const [adjacent, notAdjacent] = edges.reduce(\n (acc, cur) => fst(cur) === root ?\n [[...fst(acc), cur], snd(acc)] :\n [fst(acc), [...snd(acc), cur]],\n [[], []])\n\n const t = buildTree1Depth(adjacent, root)\n if (t.children.length === 0) {\n return { name: root }\n }\n t.children = t.children.map(tre => buildTree(notAdjacent, tre.name))\n return t\n}\n\nexport const doubleQuotes = (str = \"\") =>\n str.split('\"').slice(0, -1).filter((_, idx) => idx % 2 === 1)\n\nconst buildTree1Depth = (edges = [], parent = \"\") => ({\n name: parent,\n children: edges.reduce((acc, cur) => fst(cur) === parent ? [...acc, { name: snd(cur) }] : acc, [])\n})","import { buildTree } from \"./functional\"\n\n/* add new conferences here */\nconst edges = [\n [\"All Areas\", \"AI\"],\n\n [\"AI\", \"Artificial intelligence\"],\n [\"Artificial intelligence\", \"AAAI\"],\n [\"Artificial intelligence\", \"IJCAI\"],\n\n [\"AI\", \"Computer vision\"],\n [\"Computer vision\", \"CVPR\"],\n [\"Computer vision\", \"ICCV\"],\n [\"Computer vision\", \"ECCV\"],\n\n [\"AI\", \"Data mining\"],\n [\"Data mining\", \"KDD\"],\n [\"Data mining\", \"CIKM\"],\n [\"Data mining\", \"ICDM\"],\n\n [\"AI\", \"Machine learning\"],\n [\"Machine learning\", \"ICLR\"],\n [\"Machine learning\", \"ICML\"],\n [\"Machine learning\", \"NeurIPS\"],\n\n [\"AI\", \"Natural language processing\"],\n [\"Natural language processing\", \"ACL\"],\n [\"Natural language processing\", \"EMNLP\"],\n [\"Natural language processing\", \"NAACL\"],\n\n [\"AI\", \"The Web & information retrieval\"],\n [\"The Web & information retrieval\", \"SIGIR\"],\n [\"The Web & information retrieval\", \"WWW\"],\n\n [\"All Areas\", \"Systems\"],\n\n [\"Systems\", \"Computer architecture\"],\n [\"Computer architecture\", \"ASPLOS\"],\n [\"Computer architecture\", \"ISCA\"],\n [\"Computer architecture\", \"MICRO\"],\n [\"Computer architecture\", \"HPCA\"],\n\n [\"Systems\", \"Computer network\"],\n [\"Computer network\", \"SIGCOMM\"],\n [\"Computer network\", \"NSDI\"],\n\n [\"Systems\", \"Computer security\"],\n [\"Computer security\", \"NDSS\"],\n [\"Computer security\", \"Usenix\"],\n [\"Computer security\", \"SP\"],\n [\"Computer security\", \"CCS\"],\n\n [\"Systems\", \"Computer security 2\"],\n [\"Computer security 2\", \"ACSAC\"],\n [\"Computer security 2\", \"ASIACCS\"],\n [\"Computer security 2\", \"EUROSP\"],\n\n [\"Systems\", \"Databases\"],\n [\"Databases\", \"SIGMOD\"],\n [\"Databases\", \"VLDB\"],\n\n [\"Systems\", \"Design automation\"],\n [\"Design automation\", \"DAC\"],\n [\"Design automation\", \"ICCAD\"],\n\n [\"Systems\", \"High-performance computing\"],\n [\"High-performance computing\", \"HPDC\"],\n [\"High-performance computing\", \"ICS\"],\n [\"High-performance computing\", \"SC\"],\n\n [\"Systems\", \"Measurement & perf. analysis\"],\n [\"Measurement & perf. analysis\", \"IMC\"],\n [\"Measurement & perf. analysis\", \"SIGMETRICS\"],\n\n [\"Systems\", \"Embedded & real-time systems\"],\n [\"Embedded & real-time systems\", \"EMSOFT\"],\n [\"Embedded & real-time systems\", \"RTAS\"],\n [\"Embedded & real-time systems\", \"RTSS\"],\n\n [\"Systems\", \"Mobile computing\"],\n [\"Mobile computing\", \"MobiCom\"],\n [\"Mobile computing\", \"MobiSys\"],\n [\"Mobile computing\", \"SenSys\"],\n\n [\"Systems\", \"Operating systems\"],\n [\"Operating systems\", \"OSDI\"],\n [\"Operating systems\", \"SOSP\"],\n [\"Operating systems\", \"ATC\"],\n [\"Operating systems\", \"EuroSYS\"],\n\n [\"Systems\", \"Software engineering\"],\n [\"Software engineering\", \"FSE\"],\n [\"Software engineering\", \"ICSE\"],\n [\"Software engineering\", \"ASE\"],\n [\"Software engineering\", \"ISSTA\"],\n\n [\"Systems\", \"Programming languages\"],\n [\"Programming languages\", \"PACMPL\"],\n [\"Programming languages\", \"PLDI\"],\n\n [\"All Areas\", \"Theory\"],\n\n [\"Theory\", \"Algorithms & complexity\"],\n [\"Algorithms & complexity\", \"FOCS\"],\n [\"Algorithms & complexity\", \"SODA\"],\n [\"Algorithms & complexity\", \"STOC\"],\n\n [\"Theory\", \"Cryptography\"],\n [\"Cryptography\", \"CRYPTO\"],\n [\"Cryptography\", \"EuroCrypt\"],\n\n [\"Theory\", \"Logic & verification\"],\n [\"Logic & verification\", \"LICS\"],\n\n [\"All Areas\", \"Interdisciplinary Areas\"],\n\n [\"Interdisciplinary Areas\", \"Computer science education\"],\n [\"Computer science education\", \"SIGCSE\"],\n\n [\"Interdisciplinary Areas\", \"Economics & computation\"],\n [\"Economics & computation\", \"EC\"],\n [\"Economics & computation\", \"WINE\"],\n \n [\"Interdisciplinary Areas\", \"Human-computer interaction\"],\n [\"Human-computer interaction\", \"CHI\"],\n [\"Human-computer interaction\", \"UbiComp\"],\n [\"Human-computer interaction\", \"UIST\"],\n\n [\"Interdisciplinary Areas\", \"Robotics\"],\n [\"Robotics\", \"ICRA\"],\n [\"Robotics\", \"IROS\"],\n [\"Robotics\", \"RSS\"],\n]\n\nconst comments = {\n \"ACL\": \"(long)\",\n \"PLDI\": \"(2018 - 2022)\",\n \"SOSP\": \"(2017 - 2023), biyearly\",\n}\n\n/**\n * Return leaves's names.\n * @typedef {{ name: string, children: [Tree] }} Tree\n * @param {Tree} tree\n * @returns {string}\n */\nconst flatten = (tree) =>\n tree.children.reduce((acc, cur) =>\n cur.children ? [...acc, ...flatten(cur)] : [...acc, cur.name]\n , [])\n\nconst conferences = {\n tree: buildTree(edges, \"All Areas\"),\n flatten,\n}\n\nexport {\n conferences,\n comments\n}","const startsWithLower = (text = \"\", tok = \"\") =>\n text.toLowerCase().startsWith(tok.toLowerCase())\n\nconst consume = (text = \"\", tok = \"\") =>\n startsWithLower(text, tok) ? \n text.substring(tok.length) :\n text\n\nconst split = (text = \"\", sep = []) => {\n if (sep.length === 0) {\n return []\n }\n const ret = []\n /* match long word first */\n sep = sep.sort((a, b) => b.length - a.length)\n \n let word = \"\"\n while (text.length !== 0) {\n let tok = \"\"\n for(tok of sep) {\n if (startsWithLower(text, tok)) {\n break\n }\n tok = \"\"\n }\n if (tok === \"\") {\n word += text.charAt(0)\n text = text.substring(1)\n } else {\n if (word !== \"\") {\n ret.push(word)\n word = \"\"\n }\n if (ret.length === 0) {\n ret.push(\"\")\n }\n ret.push(text.substring(0, tok.length))\n text = consume(text, tok)\n }\n }\n if (word !== \"\") {\n ret.push(word)\n word = \"\"\n }\n return ret\n}\n\n/**\n * \n * @param {{ text: string, highlight: string[] }} props\n * @returns \n */\nfunction Highlight(props) {\n if (props.highlight.length === 0) {\n return props.text\n }\n const parts = split(props.text, props.highlight);\n return parts.map((part, index) =>\n index % 2 === 1 ? (\n \n {part}\n \n ) : (\n part\n )\n );\n}\n\n\nexport default Highlight;\n","import { useState } from 'react';\nimport { getAbstract } from '../api';\nimport Highlight from './Highlight'\n\n/**\n * \n * @param {{ year: number, venue: string, title: string, highlight: string[] }} props\n * @returns \n */\nfunction Paper(props) {\n const [collapsed, setCollapsed] = useState(true)\n const [abstract, setAbstract] = useState('')\n const [isAbsLoaded, setIsAbsLoaded] = useState(false)\n const venueUpper = props.venue.toUpperCase()\n\n const toggleCollapsed = () => {\n const nextCollapsed = !collapsed\n setCollapsed(nextCollapsed)\n if (nextCollapsed) {\n return\n }\n if (isAbsLoaded) {\n return\n }\n getAbstract(props.year, props.venue, props.title)\n .then(([abs, err]) => {\n if (err) {\n setAbstract(\"failed to retreive an abstract: \", err)\n } else {\n setAbstract(abs)\n }\n setIsAbsLoaded(true)\n })\n }\n\n return (\n \n {\n isAbsLoaded ?\n
\n
\n {d1.name} [ delVenueList(conferences.flatten(d1))} className='underline pointer'>off | addVenueList(conferences.flatten(d1))} className='underline pointer'>on ]\n {d1.children.map(d2 =>\n
\n
\n }\n
\n \n {\n isAbsLoaded ?\n
\n
\n {d1.name} [ delVenueList(conferences.flatten(d1))} className='underline pointer'>off | addVenueList(conferences.flatten(d1))} className='underline pointer'>on ]\n {d1.children.map(d2 =>\n
\n
\n }\n
\n