Finished project.

This commit is contained in:
Kaj Forney 2022-12-18 13:09:27 -07:00
parent 96303efb3f
commit 549c16017f
Signed by: kforney
GPG key ID: 3AB4E2E04CEF656F
17 changed files with 1769 additions and 3670 deletions

View file

@ -5,10 +5,224 @@
</component>
<component name="ChangeListManager">
<list default="true" id="6abd8f67-7d6c-4fe3-ae29-007cb6851088" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/testingStuff.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/css/main.css" beforeDir="false" afterPath="$PROJECT_DIR$/css/main.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/css/animation.css" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/css/grid.css" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/css/main.css" beforeDir="false" afterPath="$PROJECT_DIR$/assets/css/main.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/fonts/IBMPlexMono-Regular.ttf" beforeDir="false" afterPath="$PROJECT_DIR$/assets/fonts/IBMPlexMono-Regular.ttf" afterDir="false" />
<change beforePath="$PROJECT_DIR$/fonts/IBMPlexSans-Regular.ttf" beforeDir="false" afterPath="$PROJECT_DIR$/assets/fonts/IBMPlexSans-Regular.ttf" afterDir="false" />
<change beforePath="$PROJECT_DIR$/fonts/Oswald-Regular.ttf" beforeDir="false" afterPath="$PROJECT_DIR$/assets/fonts/Oswald-Regular.ttf" afterDir="false" />
<change beforePath="$PROJECT_DIR$/fonts/VT323-Regular.ttf" beforeDir="false" afterPath="$PROJECT_DIR$/assets/fonts/VT323-Regular.ttf" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gamedata.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/img/background.png" beforeDir="false" afterPath="$PROJECT_DIR$/assets/img/background.png" afterDir="false" />
<change beforePath="$PROJECT_DIR$/img/logos/lunarpenguin.png" beforeDir="false" afterPath="$PROJECT_DIR$/assets/img/logos/lunarpenguin.png" afterDir="false" />
<change beforePath="$PROJECT_DIR$/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/.package-lock.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/denque/CHANGELOG.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/denque/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/denque/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/denque/index.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/denque/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/denque/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/generate-function/.travis.yml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/generate-function/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/generate-function/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/generate-function/example.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/generate-function/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/generate-function/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/generate-function/test.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/.github/dependabot.yml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/.idea/codeStyles/Project.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/.idea/codeStyles/codeStyleConfig.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/.idea/iconv-lite.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/.idea/inspectionProfiles/Project_Default.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/.idea/modules.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/.idea/vcs.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/Changelog.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/dbcs-codec.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/dbcs-data.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/internal.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/sbcs-codec.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/sbcs-data-generated.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/sbcs-data.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/tables/big5-added.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/tables/cp936.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/tables/cp949.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/tables/cp950.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/tables/eucjp.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/tables/gbk-added.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/tables/shiftjis.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/utf16.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/utf32.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/encodings/utf7.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/lib/bom-handling.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/lib/index.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/lib/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/lib/streams.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/iconv-lite/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/is-property/.npmignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/is-property/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/is-property/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/is-property/is-property.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/is-property/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/long/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/long/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/long/dist/long.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/long/dist/long.js.map" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/long/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/long/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/long/src/long.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/lru-cache/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/lru-cache/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/lru-cache/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/lru-cache/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/License" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/index.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/auth_41.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/auth_plugins/caching_sha2_password.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/auth_plugins/caching_sha2_password.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/auth_plugins/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/auth_plugins/mysql_native_password.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/auth_plugins/sha256_password.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/auth_switch.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/binlog_dump.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/change_user.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/client_handshake.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/close_statement.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/command.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/execute.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/ping.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/prepare.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/query.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/quit.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/register_slave.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/commands/server_handshake.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/compressed_protocol.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/connection.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/connection_config.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/charset_encodings.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/charsets.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/client.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/commands.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/cursor.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/encoding_charset.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/errors.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/field_flags.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/server_status.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/session_track.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/ssl_profiles.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/constants/types.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/helpers.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packet_parser.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/auth_switch_request.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/auth_switch_request_more_data.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/auth_switch_response.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/binary_row.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/binlog_dump.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/binlog_query_statusvars.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/change_user.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/close_statement.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/column_definition.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/execute.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/handshake.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/handshake_response.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/packet.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/prepare_statement.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/prepared_statement_header.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/query.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/register_slave.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/resultset_header.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/ssl_request.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/packets/text_row.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/parsers/binary_parser.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/parsers/parser_cache.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/parsers/string.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/parsers/text_parser.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/pool.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/pool_cluster.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/pool_config.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/pool_connection.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/results_stream.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/lib/server.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/promise.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/promise.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/LICENSE.txt" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/index.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/info.txt" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/Connection.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/Pool.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/PoolCluster.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/PoolConnection.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/protocol/packets/Field.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/protocol/packets/FieldPacket.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/protocol/packets/OkPacket.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/protocol/packets/ResultSetHeader.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/protocol/packets/RowDataPacket.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/protocol/packets/index.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/protocol/sequences/Query.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/mysql2/typings/mysql/lib/protocol/sequences/Sequence.d.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/Changelog.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/lru-cache/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/lru-cache/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/lru-cache/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/lru-cache/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/yallist/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/yallist/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/yallist/iterator.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/yallist/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/node_modules/yallist/yallist.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/named-placeholders/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/pseudomap/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/pseudomap/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/pseudomap/map.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/pseudomap/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/pseudomap/pseudomap.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/pseudomap/test/basic.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/safer-buffer/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/safer-buffer/Porting-Buffer.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/safer-buffer/Readme.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/safer-buffer/dangerous.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/safer-buffer/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/safer-buffer/safer.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/safer-buffer/tests.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/.jshintrc" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/.npmignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/AUTHORS" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/Makefile" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/lib/.npmignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/lib/seq-queue.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/seq-queue/test/seq-queue-test.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/sqlstring/HISTORY.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/sqlstring/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/sqlstring/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/sqlstring/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/sqlstring/lib/SqlString.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/sqlstring/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/yallist/LICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/yallist/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/yallist/iterator.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/yallist/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/node_modules/yallist/yallist.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/package-lock.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/server.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/testingStuff.html" beforeDir="false" afterPath="$PROJECT_DIR$/testingStuff.html" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -34,28 +248,32 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"DefaultHtmlFileTemplate": "HTML File",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"WebServerToolWindowFactoryState": "false",
"last_opened_file_path": "/home/kforney/Documents/bsu/gimm260/gimm260-data-visualization/oldStuff",
"list.type.of.created.stylesheet": "CSS",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"vue.rearranger.settings.migration": "true"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;DefaultHtmlFileTemplate&quot;: &quot;HTML File&quot;,
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/kforney/Documents/bsu/gimm260/gimm260-data-visualization/js&quot;,
&quot;list.type.of.created.stylesheet&quot;: &quot;CSS&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}]]></component>
}</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/js" />
<recent name="$PROJECT_DIR$/oldStuff" />
<recent name="$PROJECT_DIR$" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/assets" />
</key>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
@ -69,7 +287,9 @@
<workItem from="1666713705732" duration="5754000" />
<workItem from="1667279464861" duration="6315000" />
<workItem from="1668530352304" duration="3000" />
<workItem from="1670894551811" duration="14996000" />
<workItem from="1670894551811" duration="35256000" />
<workItem from="1670940117915" duration="208000" />
<workItem from="1671393553992" duration="111000" />
</task>
<servers />
</component>

Binary file not shown.

View file

@ -11,7 +11,7 @@ body{
background-color: #161A25;
color: #8FC4E6;
font-family: 'IBM Plex Mono', monospace;
background-image: url("/img/background.png");
background-image: url("../img/background.png");
}
h1{
@ -70,6 +70,19 @@ a:visited {
color: #FFBC42;
}
/*fix D3 fonts*/
svg > svg > a {
font-family: 'IBM Plex Mono', monospace;
font-size: 11px;
color: #FFBC42;
}
svg > svg > g > g > text {
color: steelblue;
font-size: 13px;
}
iframe[src*=youtube]
{
text-align: center;
@ -84,11 +97,21 @@ iframe[src*=youtube]
width: 100%;
}
svg {
width: auto;
height: auto;
}
th, td {
padding-left: 20px;
padding-right: 20px;
}
th {
color: #FFBC42;
background-color: #283044;
}
tr:nth-child(even) {
background-color: #283044;
}
@ -179,6 +202,7 @@ button {
min-height: 85px;
}
@media only screen and (min-width: 768px) {
#footer {
position: fixed;
@ -259,4 +283,82 @@ button {
.lastOnMobile{
display: table-footer-group;
}
}
}
/**Animations**/
@keyframes titlePulse {
0% {text-shadow: #B17300 3px 3px 7px;}
75% {text-shadow: #B17300 3px 3px 7px;}
80% {text-shadow: lightsteelblue 3px 3px 7px;}
90% {text-shadow: steelblue 3px 3px 7px;}
100% {text-shadow: #B17300 3px 3px 7px;}
}
.titlePulse {
animation-name: titlePulse;
animation-duration: 2s;
animation-iteration-count: infinite;
}
@keyframes wobble {
0% {rotate: 0deg;}
33% {rotate: 15deg;}
66% {rotate: -15deg;}
100% {rotate: 0deg;}
}
.wobble {
animation-name: wobble;
animation-duration: 10s;
animation-iteration-count: infinite;
}
/**Grid system**/
* {
box-sizing: border-box;
}
/* For mobile phones: */
[class*="col-"] {
width: 100%;
}
@media only screen and (min-width: 768px) {
/* For desktop: */
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
}
[class*="col-"] {
float: left;
padding: 15px;
border-radius: 20px;
/**border: 1px solid red;**/
}
.row::after {
content: "";
clear: both;
display: table;
}
/** Image - https://www.w3schools.com/css/css_rwd_grid.asp **/
img {
max-width: 100%;
height: auto;
}
/** Overflow (for tables) - https://www.w3schools.com/howto/howto_css_table_responsive.asp **/
.overflow {
overflow-x:auto;
}

View file

Before

Width:  |  Height:  |  Size: 397 KiB

After

Width:  |  Height:  |  Size: 397 KiB

View file

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 178 KiB

View file

@ -1,26 +0,0 @@
@keyframes titlePulse {
0% {text-shadow: #B17300 3px 3px 7px;}
75% {text-shadow: #B17300 3px 3px 7px;}
80% {text-shadow: lightsteelblue 3px 3px 7px;}
90% {text-shadow: steelblue 3px 3px 7px;}
100% {text-shadow: #B17300 3px 3px 7px;}
}
.titlePulse {
animation-name: titlePulse;
animation-duration: 2s;
animation-iteration-count: infinite;
}
@keyframes wobble {
0% {rotate: 0deg;}
33% {rotate: 15deg;}
66% {rotate: -15deg;}
100% {rotate: 0deg;}
}
.wobble {
animation-name: wobble;
animation-duration: 10s;
animation-iteration-count: infinite;
}

View file

@ -1,49 +0,0 @@
/** Grid system - https://www.w3schools.com/css/css_rwd_grid.asp **/
* {
box-sizing: border-box;
}
/* For mobile phones: */
[class*="col-"] {
width: 100%;
}
@media only screen and (min-width: 768px) {
/* For desktop: */
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
}
[class*="col-"] {
float: left;
padding: 15px;
border-radius: 20px;
/**border: 1px solid red;**/
}
.row::after {
content: "";
clear: both;
display: table;
}
/** Image - https://www.w3schools.com/css/css_rwd_grid.asp **/
img {
max-width: 100%;
height: auto;
}
/** Overflow (for tables) - https://www.w3schools.com/howto/howto_css_table_responsive.asp **/
.overflow {
overflow-x:auto;
}

3
feedback.txt Normal file
View file

@ -0,0 +1,3 @@
Feedback incorporated into this project:
• Organization: Files have been neatly organized underneath the “assets” directory.
• A brief conclusion has been added to summarize most of the narrative.

File diff suppressed because one or more lines are too long

1033
index.html

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,241 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testing</title>
<script type="module">
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
let parsedData = {
"name": "Total Reports",
"children": [
{"name": "Working",
"children": [
{"name": "Windowing Faults", "size": 0},
{"name": "Performance Faults", "size": 0},
{"name": "Save Game Faults", "size": 0},
{"name": "Graphical Faults", "size": 0},
{"name": "Audio Faults", "size": 0},
{"name": "Input Faults", "size": 0},
{"name": "Stability Faults", "size": 0},
{"name": "Significant Bugs", "size": 0},
{"name": "No Issues", "size": 0}
]},
{"name": "Nonfunctional", "size": 0}
]
};
const jsonData = d3.json("http://localhost:8888");
//const jsonData = d3.json("gamedata.json");
jsonData.then(function (data){
let dataset = data.reports;
processData(dataset);
});
function processData(data) {
console.log(data);
for(let i = 0; i < data.length; i++) {
if(data[i].verdict == 0)
{
parsedData.children[1].size++;
}
else if(data[i].verdict == 1) {
if(data[i].windowingFaults == 1) {
parsedData.children[0].children[0].size++;
continue;
}
if(data[i].performanceFaults == 1) {
parsedData.children[0].children[1].size++;
continue;
}
if(data[i].saveGameFaults == 1) {
parsedData.children[0].children[2].size++;
continue;
}
if(data[i].graphicalFaults == 1) {
parsedData.children[0].children[3].size++;
continue;
}
if(data[i].audioFaults == 1) {
parsedData.children[0].children[4].size++;
continue;
}
if(data[i].inputFaults == 1) {
parsedData.children[0].children[5].size++;
continue;
}
if(data[i].stabilityFaults == 1) {
parsedData.children[0].children[6].size++;
continue;
}
if(data[i].significantBugs == 1) {
parsedData.children[0].children[7].size++;
continue;
}
if((
data[i].windowingFaults == 0 &&
data[i].performanceFaults == 0 &&
data[i].saveGameFaults == 0 &&
data[i].graphicalFaults == 0 &&
data[i].audioFaults == 0 &&
data[i].inputFaults == 0 &&
data[i].stabilityFaults == 0 &&
data[i].significantBugs == 0
) || (data[i].verdictOOB == 1)
) {
parsedData.children[0].children[8].size++;
}
}
}
console.log(parsedData);
let chart = Icicle(parsedData, {
value: d => d.size, // size of each node (file); null for internal nodes (folders)
label: d => d.name, // display name for each cell
title: (d, n) => `${n.ancestors().reverse().map(d => d.data.name).join(".")}\n${n.value.toLocaleString("en")}`, // hover text
width: 500,
height: 500
})
console.log(chart);
document.getElementById("dataViz").appendChild(chart);
}
// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/icicle
function Icicle(data, { // data is either tabular (array of objects) or hierarchy (nested objects)
path, // as an alternative to id and parentId, returns an array identifier, imputing internal nodes
id = Array.isArray(data) ? d => d.id : null, // if tabular data, given a d in data, returns a unique identifier (string)
parentId = Array.isArray(data) ? d => d.parentId : null, // if tabular data, given a node d, returns its parents identifier
children, // if hierarchical data, given a d in data, returns its children
format = ",", // format specifier string or function for values
value, // given a node d, returns a quantitative value (for area encoding; null for count)
sort = (a, b) => d3.descending(a.value, b.value), // how to sort nodes prior to layout
label, // given a node d, returns the name to display on the rectangle
title, // given a node d, returns its hover text
link, // given a node d, its link (if any)
linkTarget = "_blank", // the target attribute for links (if any)
width = 640, // outer width, in pixels
height = 400, // outer height, in pixels
margin = 0, // shorthand for margins
marginTop = margin, // top margin, in pixels
marginRight = margin, // right margin, in pixels
marginBottom = margin, // bottom margin, in pixels
marginLeft = margin, // left margin, in pixels
padding = 1, // cell padding, in pixels
round = false, // whether to round to exact pixels
color = d3.interpolateRainbow, // color scheme, if any
fill = "#ccc", // fill for node rects (if no color encoding)
fillOpacity = 0.6, // fill opacity for node rects
} = {}) {
// If id and parentId options are specified, or the path option, use d3.stratify
// to convert tabular data to a hierarchy; otherwise we assume that the data is
// specified as an object {children} with nested objects (a.k.a. the “flare.json”
// format), and use d3.hierarchy.
const root = path != null ? d3.stratify().path(path)(data)
: id != null || parentId != null ? d3.stratify().id(id).parentId(parentId)(data)
: d3.hierarchy(data, children);
// Compute the values of internal nodes by aggregating from the leaves.
value == null ? root.count() : root.sum(d => Math.max(0, value(d)));
// Compute formats.
if (typeof format !== "function") format = d3.format(format);
// Sort the leaves (typically by descending value for a pleasing layout).
if (sort != null) root.sort(sort);
// Compute the partition layout. Note that x and y are swapped!
d3.partition()
.size([height - marginTop - marginBottom, width - marginLeft - marginRight])
.padding(padding)
.round(round)
(root);
// Construct a color scale.
if (color != null) {
color = d3.scaleSequential([0, root.children.length - 1], color).unknown(fill);
root.children.forEach((child, i) => child.index = i);
}
const svg = d3.create("svg")
.attr("viewBox", [-marginLeft, -marginTop, width, height])
.attr("width", width)
.attr("height", height)
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("font-family", "sans-serif")
.attr("font-size", 10);
const cell = svg
.selectAll("a")
.data(root.descendants())
.join("a")
.attr("xlink:href", link == null ? null : d => link(d.data, d))
.attr("target", link == null ? null : linkTarget)
.attr("transform", d => `translate(${d.y0},${d.x0})`);
cell.append("rect")
.attr("width", d => d.y1 - d.y0)
.attr("height", d => d.x1 - d.x0)
.attr("fill", color ? d => color(d.ancestors().reverse()[1]?.index) : fill)
.attr("fill-opacity", fillOpacity);
const text = cell.filter(d => d.x1 - d.x0 > 10).append("text")
.attr("x", 4)
.attr("y", d => Math.min(9, (d.x1 - d.x0) / 2))
.attr("dy", "0.32em");
if (label != null) text.append("tspan")
.text(d => label(d.data, d));
text.append("tspan")
.attr("fill-opacity", 0.7)
.attr("dx", label == null ? null : 3)
.text(d => format(d.value));
if (title != null) cell.append("title")
.text(d => title(d.data, d));
return svg.node();
}
function responsivefy(svg) {
// get container + svg aspect ratio
var container = d3.select(svg.node().parentNode),
width = parseInt(svg.style("width")),
height = parseInt(svg.style("height")),
aspect = width / height;
// add viewBox and preserveAspectRatio properties,
// and call resize so that svg resizes on inital page load
svg.attr("viewBox", "0 0 " + width + " " + height)
.attr("perserveAspectRatio", "xMinYMid")
.call(resize);
// to register multiple listeners for same event type,
// you need to add namespace, i.e., 'click.foo'
// necessary if you call invoke this function for multiple svgs
// api docs: https://github.com/mbostock/d3/wiki/Selections#on
d3.select(window).on("resize." + container.attr("id"), resize);
// get width of container and resize svg to fit it
function resize() {
var targetWidth = parseInt(container.style("width"));
svg.attr("width", targetWidth);
svg.attr("height", Math.round(targetWidth / aspect));
}
}
</script>
</head>
<body>
<div>
<svg width="1152" height="2400" id="dataViz"></svg>
</div>
</body>
</html>

View file

@ -20,7 +20,8 @@ const server = http.createServer((request, response) => {
const getParameters = url.parse(request.url, true).query;
//SELECT statement variables
let selectSql = 'SELECT game_title, timestamp, verdict, systemInfo_os, systemInfo_cpu, systemInfo_gpu, notes_summary FROM protonReports',
//let selectSql = 'SELECT game_title, timestamp, verdict, systemInfo_os, systemInfo_cpu, systemInfo_gpu, notes_summary FROM protonReports',
let selectSql = 'SELECT * FROM protonReports',
whereStatements = [],
orderByStatements = [],
queryParameters = [];

View file

@ -4,49 +4,188 @@
<meta charset="UTF-8">
<title>Testing</title>
<script type="module">
<script type="module" id="cuphead">
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
//const jsonData = d3.json("http://localhost:8888");
const jsonData = d3.json("gamedata.json");
const jsonData = d3.json("http://localhost:8888");
jsonData.then(function (data){
//let dataset = data.reports;
processData(data);
let dataset = data.reports;
processData(dataset);
});
function processData(data) {
let reportsPerMonth = [["2019-10",0]];
let parsedCupheadData = [];
let indexWorking = 0;
let indexBroken = 1;
let prevDate = 14;
let index = 0;
let prevMonth = 10;
parsedCupheadData[indexWorking] = new Object();
parsedCupheadData[indexWorking].date = new Date("2019-11-01");
parsedCupheadData[indexWorking].title = "Working";
parsedCupheadData[indexWorking].number = 0;
parsedCupheadData[indexBroken] = new Object();
parsedCupheadData[indexBroken].date = new Date("2019-11-01");
parsedCupheadData[indexBroken].title = "Borked";
parsedCupheadData[indexBroken].number = 0;
for(let i = 0; i < data.length; i++) {
let currentValue = new Date(data[i].timestamp * 1000);
let currentYear = currentValue.getFullYear();
let currentMonth = currentValue.getMonth() + 1;
let currentReport = data[i];
let currentDate = new Date(data[i].timestamp * 1000);
let dateString = currentDate.getFullYear().toString() + "-" + currentDate.getMonth().toString() + "-" + currentDate.getDate().toString();
if(currentMonth != prevMonth) {
prevMonth = currentMonth;
index++;
reportsPerMonth[index] = ["",0];
reportsPerMonth[index][0] = (currentYear.toString() + "-" + currentMonth.toString());
reportsPerMonth[index][1] = 0;
if(data[i].game_title != "Cuphead")
{continue;} else {
if(currentDate.getDate() != prevDate) {
prevDate = currentDate.getDate();
indexBroken = indexBroken + 2;
indexWorking = indexWorking + 2;
parsedCupheadData[indexWorking] = new Object();
parsedCupheadData[indexWorking].date = currentDate;
parsedCupheadData[indexWorking].title = "Working";
parsedCupheadData[indexWorking].number = 0;
parsedCupheadData[indexBroken] = new Object();
parsedCupheadData[indexBroken].date = currentDate;
parsedCupheadData[indexBroken].title = "Borked";
parsedCupheadData[indexBroken].number = 0;
}
if(data[i].verdict == 0) {
parsedCupheadData[indexBroken].number++;
}
if(data[i].verdict == 1) {
parsedCupheadData[indexWorking].number++;
}
}
reportsPerMonth[index][1]++;
}
console.log(reportsPerMonth);
document.getElementById("visCuphead").appendChild(StackedAreaChart(parsedCupheadData, {
x: d => d.date,
y: d => d.number,
z: d => d.title,
yLabel: "Number of Reports--Cuphead",
width: 700,
height: 250
}
));
}
// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/normalized-stacked-area-chart
function StackedAreaChart(data, {
x = ([x]) => x, // given d in data, returns the (ordinal) x-value
y = ([, y]) => y, // given d in data, returns the (quantitative) y-value
z = () => 1, // given d in data, returns the (categorical) z-value
marginTop = 20, // top margin, in pixels
marginRight = 30, // right margin, in pixels
marginBottom = 30, // bottom margin, in pixels
marginLeft = 40, // left margin, in pixels
width = 640, // outer width, in pixels
height = 400, // outer height, in pixels
xType = d3.scaleUtc, // type of x-scale
xDomain, // [xmin, xmax]
xRange = [marginLeft, width - marginRight], // [left, right]
yType = d3.scaleLinear, // type of y-scale
yDomain, // [ymin, ymax]
yRange = [height - marginBottom, marginTop], // [bottom, top]
zDomain, // array of z-values
offset = d3.stackOffsetExpand, // stack offset method
order = d3.stackOrderNone, // stack order method
yLabel, // a label for the y-axis
xFormat, // a format specifier string for the x-axis
yFormat = "%", // a format specifier string for the y-axis
colors = d3.schemeDark2, // an array of colors for the (z) categories
} = {}) {
// Compute values.
const X = d3.map(data, x);
const Y = d3.map(data, y);
const Z = d3.map(data, z);
// Compute default x- and z-domains, and unique the z-domain.
if (xDomain === undefined) xDomain = d3.extent(X);
if (zDomain === undefined) zDomain = Z;
zDomain = new d3.InternSet(zDomain);
// Omit any data not present in the z-domain.
const I = d3.range(X.length).filter(i => zDomain.has(Z[i]));
// Compute a nested array of series where each series is [[y1, y2], [y1, y2],
// [y1, y2], …] representing the y-extent of each stacked rect. In addition,
// each tuple has an i (index) property so that we can refer back to the
// original data point (data[i]). This code assumes that there is only one
// data point for a given unique x- and z-value.
const series = d3.stack()
.keys(zDomain)
.value(([x, I], z) => Y[I.get(z)])
.order(order)
.offset(offset)
(d3.rollup(I, ([i]) => i, i => X[i], i => Z[i]))
.map(s => s.map(d => Object.assign(d, {i: d.data[1].get(s.key)})));
// Compute the default y-domain. Note: diverging stacks can be negative.
if (yDomain === undefined) yDomain = d3.extent(series.flat(2));
// Construct scales and axes.
const xScale = xType(xDomain, xRange);
const yScale = yType(yDomain, yRange);
const color = d3.scaleOrdinal(zDomain, colors);
const xAxis = d3.axisBottom(xScale).ticks(width / 80, xFormat).tickSizeOuter(0);
const yAxis = d3.axisLeft(yScale).ticks(height / 50, yFormat);
const area = d3.area()
.x(({i}) => xScale(X[i]))
.y0(([y1]) => yScale(y1))
.y1(([, y2]) => yScale(y2));
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");
svg.append("g")
.selectAll("path")
.data(series)
.join("path")
.attr("fill", ([{i}]) => color(Z[i]))
.attr("d", area)
.append("title")
.text(([{i}]) => Z[i]);
svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(xAxis)
.call(g => g.select(".domain").remove());
svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(yAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line")
.filter(d => d === 0 || d === 1)
.clone()
.attr("x2", width - marginLeft - marginRight))
.call(g => g.append("text")
.attr("x", -marginLeft)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text(yLabel));
return Object.assign(svg.node(), {scales: {color}});
}
}
</script>
</head>
<body>
<div id="dataViz">
<svg width="1000" height="500"></svg>
<div>
<svg width="500" height="500" id="visCuphead" class="overflow"></svg>
</div>
</body>