├── .prettierignore ├── .eslintignore ├── src ├── css │ ├── container.css │ ├── SetParty.css │ ├── MobSetParty.css │ ├── mobile.css │ ├── text.css │ ├── daum.css │ └── App.css ├── util │ ├── ubase.js │ ├── comb.js │ ├── dynamo.ts │ ├── dynamo.js │ ├── datePath.ts │ ├── datePrefix.ts │ ├── datePath.js │ ├── datePrefix.js │ ├── comment_char.ts │ ├── comment_char.js │ ├── char.ts │ ├── rev_parse.ts │ ├── rev_parse.js │ ├── char.js │ ├── distance.ts │ ├── prime.js │ ├── distance.js │ ├── prime.ts │ ├── char_parse.ts │ └── char_parse.js ├── index.js ├── components │ ├── App.js │ ├── Cutter.js │ ├── MobCutter.js │ ├── Routes.js │ ├── Party.js │ ├── MobParty.js │ ├── CharSet.js │ ├── Block.tsx │ ├── SetParty.js │ ├── MobSetParty.js │ ├── Nav.js │ ├── MobRank.js │ ├── Rank.js │ ├── Container.js │ └── MobNav.js └── lambda │ ├── getStat.test.ts │ ├── getCount.test.ts │ ├── getImage.test.ts │ ├── getPart.test.ts │ ├── getMatch.test.ts │ ├── getStat.ts │ ├── getImage.ts │ ├── getSearch.test.ts │ ├── getComment.ts │ ├── getCount.ts │ ├── putS3Image.ts │ ├── getComment.spec.ts │ ├── getStat.test.js │ ├── getCount.test.js │ ├── getMatch.ts │ ├── getImage.test.js │ ├── putS3Image.js │ ├── getPart.test.js │ ├── getImage.js │ ├── getStat.js │ ├── getComment.js │ ├── getPart.ts │ └── getSearch.test.js ├── typedoc.json ├── public ├── back.png ├── lose.png ├── mag.png ├── part.png ├── stat.png ├── win.png ├── brand.png ├── cancel.png ├── search.png ├── favicon.jpg ├── landsol.jpeg ├── register.png ├── thumb-up.png ├── characters.jpg ├── thumb-down.png ├── arenatime │ ├── back.png │ ├── lose.png │ ├── mag.png │ ├── part.png │ ├── stat.png │ ├── win.png │ ├── brand.png │ ├── cancel.png │ ├── search.png │ ├── favicon.jpg │ ├── landsol.jpeg │ ├── register.png │ ├── thumb-up.png │ ├── characters.jpg │ ├── thumb-down.png │ ├── discord.svg │ └── github-logo.svg ├── manifest.json ├── index.html ├── discord.svg └── github-logo.svg ├── test.ts ├── docs └── assets │ └── images │ ├── icons.png │ ├── widgets.png │ ├── icons@2x.png │ └── widgets@2x.png ├── alltypes.d.ts ├── .prettierrc ├── config ├── jest │ ├── cssTransform.js │ └── fileTransform.js ├── pnpTs.js ├── modules.js ├── paths.js └── env.js ├── .nycrc ├── README.md ├── .gitignore ├── resources ├── s3-bucket.yml ├── api-gateway-errors.yml └── dynamo-db.yml ├── tsconfig.json ├── .eslintrc.js ├── scripts ├── test.js └── start.js ├── jest.config.js ├── serverless.yml └── package.json /.prettierignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | src/components 2 | src/util 3 | src/index.js -------------------------------------------------------------------------------- /src/css/container.css: -------------------------------------------------------------------------------- 1 | .top{ 2 | margin-top: 20px; 3 | } -------------------------------------------------------------------------------- /src/css/SetParty.css: -------------------------------------------------------------------------------- 1 | .char { 2 | width: 25% !important; 3 | } -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "mode": "file", 3 | "out": "docs" 4 | } -------------------------------------------------------------------------------- /src/css/MobSetParty.css: -------------------------------------------------------------------------------- 1 | .char { 2 | width: 50% !important; 3 | } -------------------------------------------------------------------------------- /public/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/back.png -------------------------------------------------------------------------------- /public/lose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/lose.png -------------------------------------------------------------------------------- /public/mag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/mag.png -------------------------------------------------------------------------------- /public/part.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/part.png -------------------------------------------------------------------------------- /public/stat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/stat.png -------------------------------------------------------------------------------- /public/win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/win.png -------------------------------------------------------------------------------- /public/brand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/brand.png -------------------------------------------------------------------------------- /public/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/cancel.png -------------------------------------------------------------------------------- /public/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/search.png -------------------------------------------------------------------------------- /public/favicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/favicon.jpg -------------------------------------------------------------------------------- /public/landsol.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/landsol.jpeg -------------------------------------------------------------------------------- /public/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/register.png -------------------------------------------------------------------------------- /public/thumb-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/thumb-up.png -------------------------------------------------------------------------------- /public/characters.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/characters.jpg -------------------------------------------------------------------------------- /public/thumb-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/thumb-down.png -------------------------------------------------------------------------------- /public/arenatime/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/back.png -------------------------------------------------------------------------------- /public/arenatime/lose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/lose.png -------------------------------------------------------------------------------- /public/arenatime/mag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/mag.png -------------------------------------------------------------------------------- /public/arenatime/part.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/part.png -------------------------------------------------------------------------------- /public/arenatime/stat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/stat.png -------------------------------------------------------------------------------- /public/arenatime/win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/win.png -------------------------------------------------------------------------------- /test.ts: -------------------------------------------------------------------------------- 1 | var prime = require('nth-prime'); 2 | 3 | console.log(prime(2) * prime(7) * prime(19)); 4 | -------------------------------------------------------------------------------- /public/arenatime/brand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/brand.png -------------------------------------------------------------------------------- /public/arenatime/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/cancel.png -------------------------------------------------------------------------------- /public/arenatime/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/search.png -------------------------------------------------------------------------------- /docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/docs/assets/images/icons.png -------------------------------------------------------------------------------- /docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /public/arenatime/favicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/favicon.jpg -------------------------------------------------------------------------------- /public/arenatime/landsol.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/landsol.jpeg -------------------------------------------------------------------------------- /public/arenatime/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/register.png -------------------------------------------------------------------------------- /public/arenatime/thumb-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/thumb-up.png -------------------------------------------------------------------------------- /docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /public/arenatime/characters.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/characters.jpg -------------------------------------------------------------------------------- /public/arenatime/thumb-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/public/arenatime/thumb-down.png -------------------------------------------------------------------------------- /docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stdev17/arenatime/HEAD/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /alltypes.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-dom'; 2 | declare module 'chai'; 3 | declare module 'uuid/v4'; 4 | declare module 'uuid-base64'; -------------------------------------------------------------------------------- /src/util/ubase.js: -------------------------------------------------------------------------------- 1 | let ub = require('uuid-base64'); 2 | 3 | function ubase(str) { 4 | return ub.encode(str); 5 | } 6 | 7 | export default ubase; -------------------------------------------------------------------------------- /src/util/comb.js: -------------------------------------------------------------------------------- 1 | let co = require('js-combinatorics'); 2 | 3 | function comb (deck, num) { 4 | return co.combination(deck, num); 5 | } 6 | 7 | export default comb; -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": true, 4 | "useTabs": false, 5 | "tabWidth": 2, 6 | "trailingComma": "all", 7 | "printWidth": 80 8 | } 9 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/App'; 4 | import 'bootstrap/dist/css/bootstrap.css'; 5 | 6 | 7 | ReactDOM.render(, document.getElementById('root')); -------------------------------------------------------------------------------- /src/util/dynamo.ts: -------------------------------------------------------------------------------- 1 | import aws = require('aws-sdk'); 2 | aws.config.update({ region: 'ap-northeast-2' }); 3 | const dyn = new aws.DynamoDB(); 4 | 5 | export const dynamoQuery = (params: any): any => { 6 | return dyn.query(params).promise(); 7 | }; 8 | -------------------------------------------------------------------------------- /src/util/dynamo.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var aws = require("aws-sdk"); 4 | aws.config.update({ region: 'ap-northeast-2' }); 5 | var dyn = new aws.DynamoDB(); 6 | exports.dynamoQuery = function (params) { 7 | return dyn.query(params).promise(); 8 | }; 9 | -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Navi } from './Nav'; 4 | 5 | import '../css/App.css'; 6 | 7 | export default class App extends React.Component { 8 | render() { 9 | return ( 10 |
11 | 12 |
13 | ); 14 | } 15 | } -------------------------------------------------------------------------------- /src/util/datePath.ts: -------------------------------------------------------------------------------- 1 | import moment = require('moment'); 2 | 3 | const datePath = function() { 4 | const m = moment().add(9, 'hour'); 5 | 6 | const year = m.year(); 7 | const month = m.month()+1; 8 | const day = m.date(); 9 | 10 | let path = year + "/" + month + "/" + day + "/"; 11 | 12 | return path; 13 | }; 14 | 15 | export default datePath; -------------------------------------------------------------------------------- /src/util/datePrefix.ts: -------------------------------------------------------------------------------- 1 | import moment = require('moment'); 2 | 3 | const datePrefix = function() { 4 | const m = moment().add(9, 'hour'); 5 | 6 | const year = m.year(); 7 | const month = m.month()+1; 8 | const day = m.date(); 9 | 10 | const path = "year=" + year + "/month=" + month + "/day=" + day + "/"; 11 | 12 | return path; 13 | }; 14 | 15 | export default datePrefix; -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/util/datePath.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var moment = require("moment"); 4 | var datePath = function () { 5 | var m = moment().add(9, 'hour'); 6 | var year = m.year(); 7 | var month = m.month() + 1; 8 | var day = m.date(); 9 | var path = year + "/" + month + "/" + day + "/"; 10 | return path; 11 | }; 12 | exports["default"] = datePath; 13 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/util/datePrefix.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var moment = require("moment"); 4 | var datePrefix = function () { 5 | var m = moment().add(9, 'hour'); 6 | var year = m.year(); 7 | var month = m.month() + 1; 8 | var day = m.date(); 9 | var path = "year=" + year + "/month=" + month + "/day=" + day + "/"; 10 | return path; 11 | }; 12 | exports["default"] = datePrefix; 13 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "cache": false, 3 | "check-coverage": false, 4 | "extension": [ 5 | ".ts" 6 | ], 7 | "include": [ 8 | "src/lambda/*.ts" 9 | ], 10 | "exclude": [ 11 | "coverage/**", 12 | "node_modules/**", 13 | "**/*.d.ts", 14 | "**/*.test.ts" 15 | ], 16 | "sourceMap": true, 17 | "reporter": [ 18 | "html", 19 | "text", 20 | "text-summary" 21 | ], 22 | "all": true, 23 | "instrument": true 24 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ArenaTime 2 | 3 | 프린세스 커넥트! Re:Dive 아레나 DB 4 | 5 | https://Stdev17.github.io/arenatime 6 | 7 | ### 대전 검색 8 | 9 | 특정 덱이 포함된 대전 결과를 원하는 설정으로 검색해 보세요! 10 | 11 | ### 대전 등록 12 | 13 | 배레나, 프레나와 승패 상관 없이 최대한 많은 대전 결과를 올려 주세요. 14 | 15 | ### 부분 검색 16 | 17 | 2, 3명 조합으로도 대전 결과를 검색해 보아요! 18 | 19 | ### 메타 분석 20 | 21 | 준비 중입니다. (대전 데이터가 부족해요) 22 | 23 | ### Discord 오픈방 24 | 25 | https://discord.gg/KpENFp7 26 | 27 | 버그 제보, 기능 제안이나 자유로운 이야기를 나누러 와 주세요! -------------------------------------------------------------------------------- /src/css/mobile.css: -------------------------------------------------------------------------------- 1 | .text { 2 | margin-top: 20px; 3 | margin-bottom: 20px; 4 | margin-left: 20px; 5 | margin-right: 20px; 6 | } 7 | 8 | .party-text { 9 | margin-top: 14px; 10 | margin-bottom: 14px; 11 | margin-left: 14px; 12 | margin-right: 14px; 13 | } 14 | 15 | .five { 16 | margin-top: 5px; 17 | } 18 | 19 | .ten { 20 | margin-top: 10px; 21 | } 22 | 23 | .twenty { 24 | margin-top: 20px; 25 | } 26 | 27 | .modal-mobile { 28 | width: 400px!important; 29 | } 30 | 31 | .stat { 32 | width: 50%; 33 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | jspm_packages 8 | .nyc_output 9 | 10 | # Serverless directories 11 | .serverless 12 | 13 | # testing 14 | /coverage 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | src/util/dummy.js 21 | .DS_Store 22 | .env.local 23 | .env.development.local 24 | .env.test.local 25 | .env.production.local 26 | 27 | npm-debug.log* 28 | yarn-debug.log* 29 | yarn-error.log* 30 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ArenaTime ~ 프린세스 커넥트! Re:Dive 아레나 DB 12 | 13 | 14 |
15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /src/lambda/getStat.test.ts: -------------------------------------------------------------------------------- 1 | import test from './getStat'; 2 | import chai = require('chai'); 3 | const expect = chai.expect; 4 | 5 | describe('getStat', () => { 6 | describe('get result', () => { 7 | it('should succeed', async () => { 8 | const res: any = await test({}, {}, ['stat-table']); 9 | const count: number = res.statusCode; 10 | expect(count).to.equal(200); 11 | }); 12 | it('should fail', async () => { 13 | const res: any = await test({}, {}, ['match-tabl']); 14 | const msg: string = JSON.parse(res.body).message; 15 | expect(msg).to.equal('Getting Stats Failed'); 16 | }); 17 | }); 18 | }); -------------------------------------------------------------------------------- /src/lambda/getCount.test.ts: -------------------------------------------------------------------------------- 1 | import test from './getCount'; 2 | import chai = require('chai'); 3 | const expect = chai.expect; 4 | 5 | describe('getComment', () => { 6 | describe('query comments', () => { 7 | it('should succeed', async () => { 8 | const res: any = await test({}, {}, ['match-table']); 9 | const count: number = JSON.parse(res.body).message; 10 | expect(count).to.be.above(800); 11 | }); 12 | it('should fail', async () => { 13 | const res: any = await test({}, {}, ['match-tabl']); 14 | const count: number = JSON.parse(res.statusCode); 15 | expect(count).to.equal(400); 16 | }); 17 | }); 18 | }); -------------------------------------------------------------------------------- /resources/s3-bucket.yml: -------------------------------------------------------------------------------- 1 | Resources: 2 | PriconneArenatime: 3 | Type: AWS::S3::Bucket 4 | Properties: 5 | BucketName: "priconne-arenatime" 6 | BucketEncryption: 7 | ServerSideEncryptionConfiguration: 8 | - ServerSideEncryptionByDefault: 9 | SSEAlgorithm: AES256 10 | # Set the CORS policy 11 | CorsConfiguration: 12 | CorsRules: 13 | - 14 | AllowedOrigins: 15 | - '*' 16 | # github.io로 설정할 것 17 | AllowedHeaders: 18 | - '*' 19 | AllowedMethods: 20 | - GET 21 | - PUT 22 | - POST 23 | - DELETE 24 | - HEAD 25 | MaxAge: 3000 -------------------------------------------------------------------------------- /src/css/text.css: -------------------------------------------------------------------------------- 1 | .text { 2 | margin-top: 20px; 3 | margin-bottom: 20px; 4 | margin-left: 20px; 5 | margin-right: 20px; 6 | } 7 | 8 | .party-text { 9 | margin-top: 14px; 10 | margin-bottom: 14px; 11 | margin-left: 14px; 12 | margin-right: 14px; 13 | } 14 | 15 | .remove-underline { 16 | text-decoration: none !important; 17 | box-shadow: none !important; 18 | color: white; 19 | } 20 | 21 | .remove-underline:hover { 22 | text-decoration: none !important; 23 | color: white; 24 | } 25 | 26 | .five { 27 | margin-top: 5px; 28 | } 29 | 30 | .ten { 31 | margin-top: 10px; 32 | } 33 | 34 | .twenty { 35 | margin-top: 20px; 36 | } 37 | 38 | .modal-web { 39 | max-width: 767px!important; 40 | } 41 | 42 | .stat { 43 | width: 50%; 44 | } -------------------------------------------------------------------------------- /resources/api-gateway-errors.yml: -------------------------------------------------------------------------------- 1 | Resources: 2 | GatewayResponseDefault4XX: 3 | Properties: 4 | ResponseParameters: 5 | gatewayresponse.header.Access-Control-Allow-Headers: "'*'" 6 | gatewayresponse.header.Access-Control-Allow-Origin: "'*'" 7 | ResponseType: DEFAULT_4XX 8 | RestApiId: 9 | Ref: ApiGatewayRestApi 10 | Type: "AWS::ApiGateway::GatewayResponse" 11 | GatewayResponseDefault5XX: 12 | Properties: 13 | ResponseParameters: 14 | gatewayresponse.header.Access-Control-Allow-Headers: "'*'" 15 | gatewayresponse.header.Access-Control-Allow-Origin: "'*'" 16 | ResponseType: DEFAULT_5XX 17 | RestApiId: 18 | Ref: ApiGatewayRestApi 19 | Type: "AWS::ApiGateway::GatewayResponse" -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2017", 5 | "allowJs": true, 6 | "checkJs": false, 7 | "jsx": "react", 8 | "outDir": "./build", 9 | "rootDir": ".", 10 | "removeComments": true, 11 | "noEmit": true, 12 | "pretty": true, 13 | "skipLibCheck": true, 14 | "strict": true, 15 | "moduleResolution": "node", 16 | "esModuleInterop": true 17 | }, 18 | "typedocOptions": { 19 | "mode": "modules", 20 | "out": "docs" 21 | }, 22 | "include": [ 23 | "src/lambda/*" 24 | ], 25 | "exclude": [ 26 | "node_modules", 27 | "src/util" 28 | ], 29 | "typeRoots": [ 30 | "../node_modules/@types", 31 | "../@types" 32 | ] 33 | } -------------------------------------------------------------------------------- /config/pnpTs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolveModuleName } = require('ts-pnp'); 4 | 5 | exports.resolveModuleName = ( 6 | typescript, 7 | moduleName, 8 | containingFile, 9 | compilerOptions, 10 | resolutionHost 11 | ) => { 12 | return resolveModuleName( 13 | moduleName, 14 | containingFile, 15 | compilerOptions, 16 | resolutionHost, 17 | typescript.resolveModuleName 18 | ); 19 | }; 20 | 21 | exports.resolveTypeReferenceDirective = ( 22 | typescript, 23 | moduleName, 24 | containingFile, 25 | compilerOptions, 26 | resolutionHost 27 | ) => { 28 | return resolveModuleName( 29 | moduleName, 30 | containingFile, 31 | compilerOptions, 32 | resolutionHost, 33 | typescript.resolveTypeReferenceDirective 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | commonjs: true, 5 | es6: true, 6 | node: true, 7 | }, 8 | extends: [ 9 | 'airbnb', 10 | ], 11 | globals: { 12 | Atomics: 'readonly', 13 | SharedArrayBuffer: 'readonly', 14 | }, 15 | parser: '@typescript-eslint/parser', 16 | parserOptions: { 17 | ecmaFeatures: { 18 | jsx: true, 19 | }, 20 | ecmaVersion: 2018, 21 | }, 22 | plugins: [ 23 | 'react', 24 | '@typescript-eslint', 25 | ], 26 | extends: ['plugin:@typescript-eslint/recommended'], 27 | rules: { 28 | "@typescript-eslint/no-explicit-any": "off" 29 | }, 30 | settings: { 31 | "import/resolver": { 32 | "node": { 33 | "extensions": [".js", ".jsx", ".ts", ".tsx"] 34 | } 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /src/css/daum.css: -------------------------------------------------------------------------------- 1 | 2 | @font-face { 3 | font-family: 'GyeonggiTitleM'; 4 | src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_one@1.0/GyeonggiTitleM.woff') format('woff'); 5 | font-weight: normal; 6 | font-style: normal; 7 | } 8 | /* 9 | @font-face{ 10 | font-family:'Daum'; 11 | font-style:normal; 12 | font-weight:400; 13 | src:url('//cdn.jsdelivr.net/korean-webfonts/1/corps/daum/Daum/Daum-Regular.woff2') format('woff2'), 14 | url('//cdn.jsdelivr.net/korean-webfonts/1/corps/daum/Daum/Daum-Regular.woff') format('woff'); 15 | } 16 | @font-face{ 17 | font-family:'Daum'; 18 | font-style:normal; 19 | font-weight:700; 20 | src:url('//cdn.jsdelivr.net/korean-webfonts/1/corps/daum/Daum/Daum-SemiBold.woff2') format('woff2'), 21 | url('//cdn.jsdelivr.net/korean-webfonts/1/corps/daum/Daum/Daum-SemiBold.woff') format('woff'); 22 | } 23 | */ -------------------------------------------------------------------------------- /src/util/comment_char.ts: -------------------------------------------------------------------------------- 1 | const char = [ 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 | export default char; 77 | -------------------------------------------------------------------------------- /public/discord.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/arenatime/discord.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lambda/getImage.test.ts: -------------------------------------------------------------------------------- 1 | import test from './getImage'; 2 | import chai = require('chai'); 3 | const expect = chai.expect; 4 | 5 | const event1 = { 6 | queryStringParameters: ["test"] 7 | }; 8 | 9 | const event2 = { 10 | queryStringParameters: ["images/2019/7/31/dbbca1ef-b946-4776-8c1d-d304857b759e.jpg"] 11 | }; 12 | 13 | describe('getImage', () => { 14 | describe('get image object from bucket', () => { 15 | it('should succeed', async () => { 16 | const res: any = await test(event2, {}, ['priconne-arenatime']); 17 | const count: number = JSON.parse(res.statusCode); 18 | expect(count).to.equal(200); 19 | }); 20 | it('should fail', async () => { 21 | const res: any = await test(event1, {}, ['princonne-arenatime']); 22 | const count: number = JSON.parse(res.statusCode); 23 | expect(count).to.equal(400); 24 | }); 25 | it('should fail', async () => { 26 | const res: any = await test(event2, {}, ['princonne-arenatim']); 27 | const count: number = JSON.parse(res.statusCode); 28 | expect(count).to.equal(400); 29 | }); 30 | }); 31 | }); -------------------------------------------------------------------------------- /src/css/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | pointer-events: none; 9 | } 10 | 11 | .App-header { 12 | background-color: #282c34; 13 | min-height: 100vh; 14 | display: flex; 15 | flex-direction: column; 16 | align-items: center; 17 | justify-content: center; 18 | font-size: calc(10px + 2vmin); 19 | color: white; 20 | } 21 | 22 | body { 23 | background-image: url('/arenatime/landsol.jpeg'); 24 | background-size: 1920px 1080px; 25 | background-repeat: repeat; 26 | } 27 | 28 | .brand { 29 | margin-top: 1px; 30 | } 31 | 32 | .github { 33 | filter: invert(81%) sepia(9%) saturate(6%) hue-rotate(28deg) brightness(109%) contrast(92%); 34 | margin-left: 5px; 35 | margin-right: 4px; 36 | margin-top: 0px; 37 | margin-bottom: 6px; 38 | } 39 | 40 | .discord { 41 | filter: invert(81%) sepia(9%) saturate(6%) hue-rotate(28deg) brightness(109%) contrast(92%); 42 | margin-left: 4px; 43 | margin-right: 5px; 44 | padding-top: 6px; 45 | margin-top: 0px; 46 | margin-bottom: 6px; 47 | } -------------------------------------------------------------------------------- /src/util/comment_char.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var char = [ 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 | exports["default"] = char; 76 | -------------------------------------------------------------------------------- /src/components/Cutter.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Stage, Layer } from 'react-konva'; 3 | import { Block } from './Block.tsx'; 4 | import { getChar } from '../util/distance.ts'; 5 | 6 | var netX = 0; 7 | var netY = 0; 8 | var col = 10; 9 | var char = 90; 10 | 11 | function getX() { 12 | netX += 1; 13 | return ( 14 | ((netX - 1) % col) * (57 + 10) + 15 | 30 + 16 | Math.floor(netY / (char - (char % col))) * (col - (char % col)) * 33.5 17 | ); 18 | } 19 | 20 | function getY() { 21 | netY += 1; 22 | return Math.floor((netY - 1) / col) * (57 + 10); 23 | } 24 | 25 | export class Cutter extends Component { 26 | constructor(props) { 27 | super(props); 28 | this.state = { 29 | p: this.props.party, 30 | }; 31 | } 32 | 33 | render() { 34 | let c = getChar(); 35 | netX = 0; 36 | netY = 0; 37 | return ( 38 | 39 | 40 | {c.map((value, index) => { 41 | return ( 42 | 50 | ); 51 | })} 52 | 53 | 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/components/MobCutter.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Stage, Layer } from 'react-konva'; 3 | import { Block } from './Block.tsx'; 4 | import { getChar } from '../util/distance.ts'; 5 | 6 | var netX = 0; 7 | var netY = 0; 8 | var col = 7; 9 | var char = 90; 10 | 11 | function getX() { 12 | netX += 1; 13 | return ( 14 | ((netX - 1) % col) * (47 + 7) - 15 | 7.5 + 16 | Math.floor(netY / (char - (char % col))) * (col - (char % col)) * 27 17 | ); 18 | } 19 | 20 | function getY() { 21 | netY += 1; 22 | return Math.floor((netY - 1) / col) * (47 + 7); 23 | } 24 | 25 | export class MobCutter extends Component { 26 | constructor(props) { 27 | super(props); 28 | this.state = { 29 | p: this.props.party, 30 | }; 31 | } 32 | 33 | render() { 34 | let c = getChar(); 35 | netX = 0; 36 | netY = 0; 37 | return ( 38 | 39 | 40 | {c.map((value, index) => { 41 | return ( 42 | 50 | ); 51 | })} 52 | 53 | 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/lambda/getPart.test.ts: -------------------------------------------------------------------------------- 1 | import test from './getPart'; 2 | import chai = require('chai'); 3 | const expect = chai.expect; 4 | 5 | const event1 = { 6 | deckType: 'attack', 7 | arena: 'all', 8 | matchResult: 'attackWin', 9 | deck: { 10 | first: 'SummerKyaru', 11 | second: 'Kyouka' 12 | } 13 | }; 14 | 15 | const event2 = { 16 | deckType: 'fuck', 17 | arena: 'all', 18 | matchResult: 'attackWin', 19 | deck: { 20 | first: 'SummerKyaru', 21 | second: 'Kyouka' 22 | } 23 | }; 24 | 25 | const ev1 = { 26 | queryStringParameters: [JSON.stringify(event1)] 27 | }; 28 | 29 | const ev2 = { 30 | queryStringParameters: [JSON.stringify(event2)] 31 | }; 32 | 33 | describe('getPart', () => { 34 | describe('get part from athena', () => { 35 | it('should succeed', async () => { 36 | const res: any = await test(ev1, {}, ['match-table']); 37 | const count: number = JSON.parse(res.statusCode); 38 | expect(count).to.equal(200); 39 | }); 40 | it('should fail', async () => { 41 | const res: any = await test(ev1, {}, ['princonne-arenatime']); 42 | const count: number = JSON.parse(res.statusCode); 43 | expect(count).to.equal(400); 44 | }); 45 | it('should fail', async () => { 46 | const res: any = await test(ev2, {}, ['match-table']); 47 | const count: number = JSON.parse(res.statusCode); 48 | expect(count).to.equal(400); 49 | }); 50 | }); 51 | }); -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFileName = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFileName}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | 19 | const jest = require('jest'); 20 | const execSync = require('child_process').execSync; 21 | let argv = process.argv.slice(2); 22 | 23 | function isInGitRepository() { 24 | try { 25 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); 26 | return true; 27 | } catch (e) { 28 | return false; 29 | } 30 | } 31 | 32 | function isInMercurialRepository() { 33 | try { 34 | execSync('hg --cwd . root', { stdio: 'ignore' }); 35 | return true; 36 | } catch (e) { 37 | return false; 38 | } 39 | } 40 | 41 | // Watch unless on CI or explicitly running all tests 42 | if ( 43 | !process.env.CI && 44 | argv.indexOf('--watchAll') === -1 45 | ) { 46 | // https://github.com/facebook/create-react-app/issues/5210 47 | const hasSourceControl = isInGitRepository() || isInMercurialRepository(); 48 | argv.push(hasSourceControl ? '--watch' : '--watchAll'); 49 | } 50 | 51 | 52 | jest.run(argv); 53 | -------------------------------------------------------------------------------- /src/components/Routes.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Route, Switch } from "react-router-dom"; 3 | import { 4 | pageRegister, 5 | pageSearch, 6 | pageMatch, 7 | pagePart, 8 | pageStat, 9 | pageRank, 10 | pageMobSearch, 11 | pageMobRegister, 12 | pageMobMatch, 13 | pageMobPart, 14 | pageMobStat, 15 | pageMobRank 16 | } from "./Container"; 17 | 18 | let mobile = require('is-mobile'); 19 | 20 | export class Routes extends React.Component { 21 | render() { 22 | if (!mobile()) { 23 | return ( 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ); 34 | } else { 35 | return ( 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/lambda/getMatch.test.ts: -------------------------------------------------------------------------------- 1 | import test from './getMatch'; 2 | import chai = require('chai'); 3 | const expect = chai.expect; 4 | 5 | const event1 = { 6 | queryStringParameters: ["test"], 7 | requestContext: { 8 | identity: { 9 | sourceIp: '127.0.0.1' 10 | } 11 | } 12 | }; 13 | 14 | const event2 = { 15 | queryStringParameters: ["0PDpntEcHgXmgxBoha.ULV"], 16 | requestContext: { 17 | identity: { 18 | sourceIp: '127.0.0.1' 19 | } 20 | } 21 | }; 22 | 23 | describe('getMatch', () => { 24 | describe('get match from db', () => { 25 | it('should succeed', async () => { 26 | const res: any = await test(event2, {}, ['match-table', 'voter-table']); 27 | const count: number = JSON.parse(res.statusCode); 28 | expect(count).to.equal(200); 29 | }); 30 | it('should fail', async () => { 31 | const res: any = await test(event1, {}, ['match-table', 'voter-table']); 32 | const count: number = JSON.parse(res.statusCode); 33 | expect(count).to.equal(400); 34 | }); 35 | it('should fail for tables', async () => { 36 | const res: any = await test(event2, {}, ['match-tabl', 'voter-table']); 37 | const count: number = JSON.parse(res.statusCode); 38 | expect(count).to.equal(400); 39 | }); 40 | it('should fail for tables', async () => { 41 | const res: any = await test(event2, {}, ['match-table', 'voter-tabl']); 42 | const count: number = JSON.parse(res.statusCode); 43 | expect(count).to.equal(400); 44 | }); 45 | }); 46 | }); -------------------------------------------------------------------------------- /src/lambda/getStat.ts: -------------------------------------------------------------------------------- 1 | import aws = require('aws-sdk'); 2 | aws.config.update({region: 'ap-northeast-2'}); 3 | const dyn = new aws.DynamoDB(); 4 | let table = 'stat-table'; 5 | 6 | /** 람다 핸들러 함수 7 | * @param event http request에 인자를 담아주세요 8 | * @return Promise 형태로 response를 반환합니다 9 | */ 10 | export const handler = async (event: any, context: any): Promise => { 11 | 12 | const params = { 13 | TableName: table, 14 | ProjectionExpression: 'PropertyName, Stats' 15 | }; 16 | 17 | const items = await dyn.scan(params).promise() 18 | .then(data => { 19 | const result = { 20 | statusCode: 200, 21 | body: JSON.stringify({ 22 | message: data, 23 | runtime: context 24 | }), 25 | headers: { 26 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 27 | 'Access-Control-Allow-Credentials': true, 28 | } 29 | }; 30 | return result; 31 | }) 32 | .catch(err => { 33 | const result = { 34 | statusCode: 200, 35 | body: JSON.stringify({ 36 | message: 'Getting Stats Failed', 37 | runtime: err 38 | }), 39 | headers: { 40 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 41 | 'Access-Control-Allow-Credentials': true, 42 | } 43 | }; 44 | console.log(err); 45 | return result; 46 | }); 47 | 48 | return items; 49 | } 50 | 51 | /** 유닛 테스트에 호출되는 함수 */ 52 | async function test (event: any, context: any, args: string[]): Promise { 53 | table = args[0]; 54 | return await handler(event, context); 55 | } 56 | 57 | export default test; -------------------------------------------------------------------------------- /src/lambda/getImage.ts: -------------------------------------------------------------------------------- 1 | import aws = require('aws-sdk'); 2 | aws.config.update({region: 'ap-northeast-2'}); 3 | const s3 = new aws.S3(); 4 | let bucket = 'priconne-arenatime'; 5 | 6 | /** 람다 핸들러 함수 7 | * @param event http request에 인자를 담아주세요 8 | * @return Promise 형태로 response를 반환합니다 9 | */ 10 | export const handler = async (event: any, context: any): Promise => { 11 | 12 | const req = event.queryStringParameters[0]; 13 | 14 | const params = { 15 | Bucket: bucket, 16 | Key: req 17 | }; 18 | 19 | const get = await s3.getObject(params).promise() 20 | .then(data => { 21 | const result = { 22 | statusCode: 200, 23 | body: JSON.stringify({ 24 | message: data, 25 | runtime: context 26 | }), 27 | headers: { 28 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 29 | 'Access-Control-Allow-Credentials': true, 30 | } 31 | }; 32 | return result; 33 | }) 34 | .catch(err => { 35 | const result = { 36 | statusCode: 400, 37 | body: JSON.stringify({ 38 | message: 'Getting Item Failed', 39 | runtime: err 40 | }), 41 | headers: { 42 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 43 | 'Access-Control-Allow-Credentials': true, 44 | } 45 | }; 46 | return result; 47 | }); 48 | 49 | return get; 50 | } 51 | 52 | /** 유닛 테스트에 호출되는 함수 */ 53 | async function test (event: any, context: any, args: string[]): Promise { 54 | bucket = args[0]; 55 | return await handler(event, context); 56 | } 57 | 58 | export default test; -------------------------------------------------------------------------------- /src/lambda/getSearch.test.ts: -------------------------------------------------------------------------------- 1 | import test from './getSearch'; 2 | import chai = require('chai'); 3 | const expect = chai.expect; 4 | 5 | const event1 = { 6 | target: 'defense', 7 | arena: 'all', 8 | date: 'all', 9 | power: 'all', 10 | sort: 'netUpvotes', 11 | result: 'attackWin', 12 | deck: { 13 | first: 'Miyako', 14 | second: 'Nozomi', 15 | third: 'Tamaki', 16 | fourth: 'Ninon', 17 | fifth: 'Mitsuki' 18 | } 19 | }; 20 | 21 | const event2 = { 22 | target: 'defense', 23 | arena: 'all', 24 | date: 'all', 25 | power: 'test', 26 | sort: 'netUpvotes', 27 | result: 'attackWin', 28 | deck: { 29 | first: 'Miyako', 30 | second: 'Nozomi', 31 | third: 'Tamaki', 32 | fourth: 'Ninon', 33 | fifth: 'Mitsuki' 34 | } 35 | }; 36 | 37 | const ev1 = { 38 | queryStringParameters: [JSON.stringify(event1)] 39 | }; 40 | 41 | const ev2 = { 42 | queryStringParameters: [JSON.stringify(event2)] 43 | }; 44 | 45 | describe('getSearch', () => { 46 | describe('get search query', () => { 47 | it('should succeed', async () => { 48 | const res: any = await test(ev1, {}, ['match-table']); 49 | const count: any = JSON.parse(res.body).message.length; 50 | expect(count).to.be.above(1); 51 | }); 52 | it('should fail', async () => { 53 | const res: any = await test(ev1, {}, ['princonne-arenatime']); 54 | const count: number = JSON.parse(res.statusCode); 55 | expect(count).to.equal(400); 56 | }); 57 | it('should fail', async () => { 58 | const res: any = await test(ev2, {}, ['match-table']); 59 | const count: number = JSON.parse(res.statusCode); 60 | expect(count).to.equal(400); 61 | }); 62 | }); 63 | }); -------------------------------------------------------------------------------- /src/lambda/getComment.ts: -------------------------------------------------------------------------------- 1 | import { dynamoQuery } from '../util/dynamo'; 2 | 3 | /** 람다 핸들러 함수 4 | * @param event http request에 인자를 담아주세요 5 | * @return Promise 형태로 response를 반환합니다 6 | */ 7 | export const handler = async (event: any, context: any): Promise => { 8 | const req = event.queryStringParameters[0]; 9 | 10 | const params = { 11 | TableName: 'comment-table', 12 | IndexName: 'matches', 13 | ExpressionAttributeValues: { 14 | ':Id': { S: req }, 15 | }, 16 | KeyConditionExpression: 'matchId = :Id', 17 | ProjectionExpression: 'commentId, charName, memo, uploadedDate', 18 | ScanIndexForward: true, 19 | }; 20 | 21 | const res: any = await dynamoQuery(params) 22 | .then((data: any) => { 23 | let status = 200; 24 | if (data.Count === 0) { 25 | status = 404; 26 | } 27 | const response = { 28 | statusCode: status, 29 | body: JSON.stringify({ 30 | message: data, 31 | runtime: context, 32 | }), 33 | headers: { 34 | 'Content-Type': 'application/json', 35 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 36 | 'Access-Control-Allow-Credentials': true, 37 | }, 38 | }; 39 | return response; 40 | }) 41 | .catch(() => { 42 | const response = { 43 | statusCode: 500, 44 | body: JSON.stringify({ 45 | message: 'Failed Comment Read', 46 | runtime: context, 47 | }), 48 | headers: { 49 | 'Content-Type': 'application/json', 50 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 51 | 'Access-Control-Allow-Credentials': true, 52 | }, 53 | }; 54 | return response; 55 | }); 56 | 57 | return res; 58 | }; 59 | -------------------------------------------------------------------------------- /src/lambda/getCount.ts: -------------------------------------------------------------------------------- 1 | import aws = require('aws-sdk'); 2 | aws.config.update({region: 'ap-northeast-2'}); 3 | const dyn = new aws.DynamoDB(); 4 | let table = 'match-table'; 5 | 6 | /** 람다 핸들러 함수 7 | * @param event http request에 인자를 담아주세요 8 | * @return Promise 형태로 response를 반환합니다 9 | */ 10 | export const handler = async (event: any, context: any): Promise => { 11 | const params = { 12 | TableName: table 13 | }; 14 | 15 | const get = await dyn.describeTable(params).promise() 16 | .then(data => { 17 | let msg = 0; 18 | if (data['Table'] !== undefined) { 19 | if (data['Table']['ItemCount'] !== undefined) { 20 | msg = data['Table']['ItemCount']; 21 | } 22 | } else { 23 | throw 'error'; 24 | } 25 | const result = { 26 | statusCode: 200, 27 | body: JSON.stringify({ 28 | message: msg, 29 | runtime: context 30 | }), 31 | headers: { 32 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 33 | 'Access-Control-Allow-Credentials': true, 34 | } 35 | }; 36 | return result; 37 | }) 38 | .catch(err => { 39 | const result = { 40 | statusCode: 400, 41 | body: JSON.stringify({ 42 | message: 'Getting Count Failed', 43 | runtime: err 44 | }), 45 | headers: { 46 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 47 | 'Access-Control-Allow-Credentials': true, 48 | } 49 | }; 50 | return result; 51 | }); 52 | 53 | return get; 54 | } 55 | 56 | /** 유닛 테스트에 호출되는 함수 */ 57 | async function test (event: any, context: any, args: string[]): Promise { 58 | table = args[0]; 59 | return await handler(event, context); 60 | } 61 | 62 | export default test; -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'json'], 3 | transform: { 4 | '^.+\\.(js|jsx)?$': 'babel-jest', 5 | '\\.ts$': ['ts-jest'], 6 | }, 7 | testEnvironment: 'node', 8 | moduleNameMapper: { 9 | '^@/(.*)$': '/$1', 10 | }, 11 | testMatch: [ 12 | //'/*.spec.(js|jsx|ts|tsx)', 13 | '/src/lambda/*.spec.(js|jsx|tsx)', 14 | '/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))', 15 | ], 16 | transformIgnorePatterns: ['/node_modules/'], 17 | globals: { 18 | 'ts-jest': { 19 | diagnostics: false, 20 | }, 21 | }, 22 | }; 23 | /* 24 | collectCoverageFrom: ['src/@@/*.{js,jsx,ts,tsx}', '!src/@@/*.d.ts'], 25 | setupFiles: ['react-app-polyfill/jsdom'], 26 | setupFilesAfterEnv: [], 27 | testMatch: [ 28 | '/src/@@/__tests__/@@/*.{js,jsx,ts,tsx}', 29 | '/src/util/*.{spec,test}.{js,jsx,ts,tsx}' 30 | ], 31 | testEnvironment: 'jest-environment-jsdom-fourteen', 32 | transform: { 33 | '^.+\\.(js|jsx|ts|tsx)$': '/node_modules/babel-jest', 34 | '^.+\\.css$': '/config/jest/cssTransform.js', 35 | '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': 36 | '/config/jest/fileTransform.js' 37 | }, 38 | transformIgnorePatterns: [ 39 | '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$', 40 | '^.+\\.module\\.(css|sass|scss)$' 41 | ], 42 | modulePaths: [], 43 | moduleNameMapper: { 44 | '^react-native$': 'react-native-web', 45 | '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy' 46 | }, 47 | moduleFileExtensions: [ 48 | 'web.js', 49 | 'js', 50 | 'web.ts', 51 | 'ts', 52 | 'web.tsx', 53 | 'tsx', 54 | 'json', 55 | 'web.jsx', 56 | 'jsx', 57 | 'node' 58 | ], 59 | watchPlugins: [ 60 | 'jest-watch-typeahead/filename', 61 | 'jest-watch-typeahead/testname' 62 | ] 63 | }; 64 | */ 65 | -------------------------------------------------------------------------------- /src/util/char.ts: -------------------------------------------------------------------------------- 1 | const char: string[] = [ 2 | 'Empty', 3 | 'Makoto', 4 | 'Mitsuki', 5 | 'Jyun', 6 | 'Kaori', 7 | 'Shiori', 8 | 'Suzuna', 9 | 'Arisa', 10 | 'Tamaki', 11 | 'Saren', 12 | 'Nozomi', 13 | 'Kokkoro', 14 | 'Hiyori', 15 | 'Ilya', 16 | 'Akari', 17 | 'Kyaru', 18 | 'Shizuru', 19 | 'Kyouka', 20 | 'Miyako', 21 | 'Djeeta', 22 | 'Monika', 23 | 'Kuuka', 24 | 'Shinobu', 25 | 'Pekorinne', 26 | 'Eriko', 27 | 'SummerPekorinne', 28 | 'Akino', 29 | 'Mimi', 30 | 'Tsumugi', 31 | 'Hatsune', 32 | 'Ayane', 33 | 'Yui', 34 | 'SummerKokkoro', 35 | 'Yukari', 36 | 'Misato', 37 | 'Anna', 38 | 'Ninon', 39 | 'Rino', 40 | 'Yori', 41 | 'Misogi', 42 | 'Yuki', 43 | 'Maho', 44 | 'Rei', 45 | 'Kurumi', 46 | 'Misaki', 47 | 'Mifuyu', 48 | 'Chika', 49 | 'Rima', 50 | 'Rin', 51 | 'Mahiru', 52 | 'Io', 53 | 'Aoi', 54 | 'Suzume', 55 | 'SummerKyaru', 56 | 'SummerTamaki', 57 | 'Tomo', 58 | 'SummerMifuyu', 59 | 'HalloweenMiyako', 60 | 'HalloweenShinobu', 61 | 'SummerSuzume', 62 | 'Matsuri', 63 | 'HalloweenMisaki', 64 | 'Christina', 65 | 'Ruka', 66 | 'Nanaka', 67 | 'ChristmasChika', 68 | 'ChristmasKurumi', 69 | 'ChristmasAyane', 70 | 'NewYui', 71 | 'NewRei', 72 | 'NewHiyori', 73 | 'ValentineShizuru', 74 | 'ValentineEriko', 75 | 'Muimi', 76 | 'Kasumi', 77 | 'Ayumi', 78 | 'Rou', 79 | 'Ann', 80 | 'Glare', 81 | 'OedoKuuka', 82 | 'OedoNinon', 83 | 'Ram', 84 | 'Rem', 85 | 'Emilia', 86 | 'SummerIo', 87 | 'SummerSuzuna', 88 | 'SummerSaren', 89 | 'SummerKaori', 90 | 'SummerMakoto', 91 | 'SummerMaho', 92 | 'Neneka', 93 | 'TransferAoi', 94 | 'Chloe', 95 | 'HalloweenMisogi', 96 | 'HalloweenKyouka', 97 | 'HalloweenMimi', 98 | 'Luna', 99 | 'Kaya', 100 | 'ChristmasNozomi', 101 | 'ChristmasChristina', 102 | 'ChristmasIlya', 103 | 'NewSuzume', 104 | 'NewKyaru', 105 | 'NewKokkoro', 106 | 'MagicalShiori', 107 | 'MagicalKasumi', 108 | 'PrincessPekorinne', 109 | 'Mio', 110 | 'Uzuki', 111 | 'Shiburin', 112 | 'Yuni', 113 | 'Chieru', 114 | 'RangerRin', 115 | ]; 116 | 117 | export default char; 118 | -------------------------------------------------------------------------------- /src/lambda/putS3Image.ts: -------------------------------------------------------------------------------- 1 | import datePath from '../util/datePath'; 2 | import aws = require('aws-sdk'); 3 | import fileType = require('file-type'); 4 | import uuid = require('uuid/v4'); 5 | aws.config.update({region: 'ap-northeast-2'}); 6 | const s3 = new aws.S3(); 7 | 8 | const getFile = function(fileMime: any, buf: any): any { 9 | 10 | const fileExt = fileMime.ext; 11 | 12 | const filePath = datePath(); 13 | const fileName = uuid() + "." + fileExt; 14 | const fileFullName = filePath + fileName; 15 | const fileFullPath = 'images/' + fileFullName; 16 | 17 | const params = { 18 | Bucket: "priconne-arenatime", 19 | Body: buf, 20 | Key: fileFullPath, 21 | ContentEncoding: 'base64', 22 | }; 23 | 24 | return params; 25 | }; 26 | 27 | /** 람다 핸들러 함수 28 | * @param event http request에 인자를 담아주세요 29 | * @return Promise 형태로 response를 반환합니다 30 | */ 31 | export const handler = async (event: any, context: any): Promise => { 32 | 33 | //let buffer = new Buffer(new Buffer(event.body).toString('base64').replace(/^data:image\/\w+;base64,/, ""),'base64'); 34 | const once = (event.body.match(/data:image\/\w+;base64,.+/)[0]).replace(/data:image\/\w+;base64,/, ""); 35 | const twice = once.replace(/\n------WebKitFormBoundary.+/, ""); 36 | const buffer = Buffer.from(twice, "base64"); 37 | 38 | const fileMime = fileType(buffer); 39 | 40 | const params = getFile(fileMime, buffer); 41 | 42 | return s3.putObject(params).promise() 43 | .then(() => { 44 | const response = { 45 | statusCode: 200, 46 | body: JSON.stringify({ 47 | message: params.Key, 48 | runtime: context 49 | }), 50 | headers: { 51 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 52 | 'Access-Control-Allow-Credentials': true, 53 | } 54 | }; 55 | return response; 56 | }) 57 | .catch(() => { 58 | const response = { 59 | statusCode: 400, 60 | body: JSON.stringify({ 61 | message: 'Upload Failed', 62 | runtime: context 63 | }), 64 | headers: { 65 | 'Access-Control-Allow-Origin': 'https://stdev17.github.io', 66 | 'Access-Control-Allow-Credentials': true, 67 | } 68 | }; 69 | return response; 70 | }); 71 | 72 | } -------------------------------------------------------------------------------- /src/util/rev_parse.ts: -------------------------------------------------------------------------------- 1 | const revchar: Record = { 2 | //Front Line 3 | Rima: '리마', 4 | Miyako: '미야코', 5 | Kuuka: '쿠우카', 6 | Jyun: '쥰', 7 | OedoKuuka: '쿠우카(오에도)', 8 | Kaori: '카오리', 9 | NewRei: '레이(새해)', 10 | Pekorinne: '페코린느', 11 | Ruka: '루카', 12 | Nozomi: '노조미', 13 | Muimi: '무이미', 14 | Makoto: '마코토', 15 | NewHiyori: '히요리(새해)', 16 | OedoNinon: '니논(오에도)', 17 | Akino: '아키노', 18 | SummerMakoto: '마코토(여름)', 19 | Matsuri: '마츠리', 20 | ValentineEriko: '에리코(발렌타인0', 21 | ChristmasAyane: '아야네(성탄절)', 22 | Tsumugi: '츠무기', 23 | Hiyori: '히요리', 24 | Misogi: '미소기', 25 | Ayane: '아야네', 26 | Tamaki: '타마키', 27 | Tomo: '토모', 28 | SummerTamaki: '타마키(여름)', 29 | Eriko: '에리코', 30 | SummerPekorinne: '페코린느(여름)', 31 | Kurumi: '쿠루미', 32 | Djeeta: '지타', 33 | Rei: '레이', 34 | Shizuru: '시즈루', 35 | Christina: '크리스티나', 36 | ChristmasKurumi: '쿠루미(성탄절)', 37 | 38 | //Middle Line 39 | Mimi: '미미', 40 | Shinobu: '시노부', 41 | ValentineShizuru: '시즈루(발렌타인)', 42 | Mahiru: '마히루', 43 | Yukari: '유카리', 44 | Monika: '모니카', 45 | Ninon: '니논', 46 | Mifuyu: '미후유', 47 | Ilya: '이리야', 48 | SummerKaori: '카오리(여름)', 49 | Saren: '사렌', 50 | Anna: '안나', 51 | HalloweenShinobu: '시노부(할로윈)', 52 | SummerMifuyu: '미후유(여름)', 53 | Kokkoro: '콧코로', 54 | Ayumi: '아유미', 55 | Glare: '글레어', 56 | SummerKokkoro: '콧코로(여름)', 57 | Rem: '렘', 58 | Ram: '람', 59 | Rin: '린', 60 | Mitsuki: '미츠키', 61 | Akari: '아카리', 62 | Yori: '요리', 63 | SummerSaren: '사렌(여름)', 64 | HalloweenMiyako: '미야코(할로윈)', 65 | 66 | //Back Line 67 | Arisa: '아리사', 68 | Ann: '앤', 69 | Rou: '루', 70 | Neneka: '네네카', 71 | Rino: '리노', 72 | Suzuna: '스즈나', 73 | SummerSuzuna: '스즈나(여름)', 74 | Shiori: '시오리', 75 | Io: '이오', 76 | SummerIo: '이오(여름)', 77 | Suzume: '스즈메', 78 | Emilia: '에밀리아', 79 | Kasumi: '카스미', 80 | Misato: '미사토', 81 | Nanaka: '나나카', 82 | NewYui: '유이(새해)', 83 | Kyaru: '캬루', 84 | Hatsune: '하츠네', 85 | Misaki: '미사키', 86 | ChristmasChika: '치카(성탄절)', 87 | SummerSuzume: '스즈메(여름)', 88 | SummerKyaru: '캬루(여름)', 89 | Aoi: '아오이', 90 | Chika: '치카', 91 | SummerMaho: '마호(여름)', 92 | Maho: '마호', 93 | Yui: '유이', 94 | Yuki: '유키', 95 | Kyouka: '쿄우카', 96 | HalloweenMisaki: '미사키(할로윈)', 97 | }; 98 | 99 | module.exports = revchar; 100 | -------------------------------------------------------------------------------- /src/util/rev_parse.js: -------------------------------------------------------------------------------- 1 | var revchar = { 2 | //Front Line 3 | Rima: '리마', 4 | Miyako: '미야코', 5 | Kuuka: '쿠우카', 6 | Jyun: '쥰', 7 | OedoKuuka: '쿠우카(오에도)', 8 | Kaori: '카오리', 9 | NewRei: '레이(새해)', 10 | Pekorinne: '페코린느', 11 | Ruka: '루카', 12 | Nozomi: '노조미', 13 | Muimi: '무이미', 14 | Makoto: '마코토', 15 | NewHiyori: '히요리(새해)', 16 | OedoNinon: '니논(오에도)', 17 | Akino: '아키노', 18 | SummerMakoto: '마코토(여름)', 19 | Matsuri: '마츠리', 20 | ValentineEriko: '에리코(발렌타인0', 21 | ChristmasAyane: '아야네(성탄절)', 22 | Tsumugi: '츠무기', 23 | Hiyori: '히요리', 24 | Misogi: '미소기', 25 | Ayane: '아야네', 26 | Tamaki: '타마키', 27 | Tomo: '토모', 28 | SummerTamaki: '타마키(여름)', 29 | Eriko: '에리코', 30 | SummerPekorinne: '페코린느(여름)', 31 | Kurumi: '쿠루미', 32 | Djeeta: '지타', 33 | Rei: '레이', 34 | Shizuru: '시즈루', 35 | Christina: '크리스티나', 36 | ChristmasKurumi: '쿠루미(성탄절)', 37 | //Middle Line 38 | Mimi: '미미', 39 | Shinobu: '시노부', 40 | ValentineShizuru: '시즈루(발렌타인)', 41 | Mahiru: '마히루', 42 | Yukari: '유카리', 43 | Monika: '모니카', 44 | Ninon: '니논', 45 | Mifuyu: '미후유', 46 | Ilya: '이리야', 47 | SummerKaori: '카오리(여름)', 48 | Saren: '사렌', 49 | Anna: '안나', 50 | HalloweenShinobu: '시노부(할로윈)', 51 | SummerMifuyu: '미후유(여름)', 52 | Kokkoro: '콧코로', 53 | Ayumi: '아유미', 54 | Glare: '글레어', 55 | SummerKokkoro: '콧코로(여름)', 56 | Rem: '렘', 57 | Ram: '람', 58 | Rin: '린', 59 | Mitsuki: '미츠키', 60 | Akari: '아카리', 61 | Yori: '요리', 62 | SummerSaren: '사렌(여름)', 63 | HalloweenMiyako: '미야코(할로윈)', 64 | //Back Line 65 | Arisa: '아리사', 66 | Ann: '앤', 67 | Rou: '루', 68 | Neneka: '네네카', 69 | Rino: '리노', 70 | Suzuna: '스즈나', 71 | SummerSuzuna: '스즈나(여름)', 72 | Shiori: '시오리', 73 | Io: '이오', 74 | SummerIo: '이오(여름)', 75 | Suzume: '스즈메', 76 | Emilia: '에밀리아', 77 | Kasumi: '카스미', 78 | Misato: '미사토', 79 | Nanaka: '나나카', 80 | NewYui: '유이(새해)', 81 | Kyaru: '캬루', 82 | Hatsune: '하츠네', 83 | Misaki: '미사키', 84 | ChristmasChika: '치카(성탄절)', 85 | SummerSuzume: '스즈메(여름)', 86 | SummerKyaru: '캬루(여름)', 87 | Aoi: '아오이', 88 | Chika: '치카', 89 | SummerMaho: '마호(여름)', 90 | Maho: '마호', 91 | Yui: '유이', 92 | Yuki: '유키', 93 | Kyouka: '쿄우카', 94 | HalloweenMisaki: '미사키(할로윈)' 95 | }; 96 | module.exports = revchar; 97 | -------------------------------------------------------------------------------- /src/util/char.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var char = [ 4 | 'Empty', 5 | 'Makoto', 6 | 'Mitsuki', 7 | 'Jyun', 8 | 'Kaori', 9 | 'Shiori', 10 | 'Suzuna', 11 | 'Arisa', 12 | 'Tamaki', 13 | 'Saren', 14 | 'Nozomi', 15 | 'Kokkoro', 16 | 'Hiyori', 17 | 'Ilya', 18 | 'Akari', 19 | 'Kyaru', 20 | 'Shizuru', 21 | 'Kyouka', 22 | 'Miyako', 23 | 'Djeeta', 24 | 'Monika', 25 | 'Kuuka', 26 | 'Shinobu', 27 | 'Pekorinne', 28 | 'Eriko', 29 | 'SummerPekorinne', 30 | 'Akino', 31 | 'Mimi', 32 | 'Tsumugi', 33 | 'Hatsune', 34 | 'Ayane', 35 | 'Yui', 36 | 'SummerKokkoro', 37 | 'Yukari', 38 | 'Misato', 39 | 'Anna', 40 | 'Ninon', 41 | 'Rino', 42 | 'Yori', 43 | 'Misogi', 44 | 'Yuki', 45 | 'Maho', 46 | 'Rei', 47 | 'Kurumi', 48 | 'Misaki', 49 | 'Mifuyu', 50 | 'Chika', 51 | 'Rima', 52 | 'Rin', 53 | 'Mahiru', 54 | 'Io', 55 | 'Aoi', 56 | 'Suzume', 57 | 'SummerKyaru', 58 | 'SummerTamaki', 59 | 'Tomo', 60 | 'SummerMifuyu', 61 | 'HalloweenMiyako', 62 | 'HalloweenShinobu', 63 | 'SummerSuzume', 64 | 'Matsuri', 65 | 'HalloweenMisaki', 66 | 'Christina', 67 | 'Ruka', 68 | 'Nanaka', 69 | 'ChristmasChika', 70 | 'ChristmasKurumi', 71 | 'ChristmasAyane', 72 | 'NewYui', 73 | 'NewRei', 74 | 'NewHiyori', 75 | 'ValentineShizuru', 76 | 'ValentineEriko', 77 | 'Muimi', 78 | 'Kasumi', 79 | 'Ayumi', 80 | 'Rou', 81 | 'Ann', 82 | 'Glare', 83 | 'OedoKuuka', 84 | 'OedoNinon', 85 | 'Ram', 86 | 'Rem', 87 | 'Emilia', 88 | 'SummerIo', 89 | 'SummerSuzuna', 90 | 'SummerSaren', 91 | 'SummerKaori', 92 | 'SummerMakoto', 93 | 'SummerMaho', 94 | 'Neneka', 95 | 'TransferAoi', 96 | 'Chloe', 97 | 'HalloweenMisogi', 98 | 'HalloweenKyouka', 99 | 'HalloweenMimi', 100 | 'Luna', 101 | 'Kaya', 102 | 'ChristmasNozomi', 103 | 'ChristmasChristina', 104 | 'ChristmasIlya', 105 | 'NewSuzume', 106 | 'NewKyaru', 107 | 'NewKokkoro', 108 | 'MagicalShiori', 109 | 'MagicalKasumi', 110 | 'PrincessPekorinne', 111 | 'Mio', 112 | 'Uzuki', 113 | 'Shiburin', 114 | 'Yuni', 115 | 'Chieru', 116 | 'RangerRin', 117 | ]; 118 | exports["default"] = char; 119 | -------------------------------------------------------------------------------- /config/modules.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const paths = require('./paths'); 6 | const chalk = require('react-dev-utils/chalk'); 7 | 8 | /** 9 | * Get the baseUrl of a compilerOptions object. 10 | * 11 | * @param {Object} options 12 | */ 13 | function getAdditionalModulePaths(options = {}) { 14 | const baseUrl = options.baseUrl; 15 | 16 | // We need to explicitly check for null and undefined (and not a falsy value) because 17 | // TypeScript treats an empty string as `.`. 18 | if (baseUrl == null) { 19 | // If there's no baseUrl set we respect NODE_PATH 20 | // Note that NODE_PATH is deprecated and will be removed 21 | // in the next major release of create-react-app. 22 | 23 | const nodePath = process.env.NODE_PATH || ''; 24 | return nodePath.split(path.delimiter).filter(Boolean); 25 | } 26 | 27 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 28 | 29 | // We don't need to do anything if `baseUrl` is set to `node_modules`. This is 30 | // the default behavior. 31 | if (path.relative(paths.appNodeModules, baseUrlResolved) === '') { 32 | return null; 33 | } 34 | 35 | // Allow the user set the `baseUrl` to `appSrc`. 36 | if (path.relative(paths.appSrc, baseUrlResolved) === '') { 37 | return [paths.appSrc]; 38 | } 39 | 40 | // Otherwise, throw an error. 41 | throw new Error( 42 | chalk.red.bold( 43 | "Your project's `baseUrl` can only be set to `src` or `node_modules`." + 44 | ' Create React App does not support other values at this time.' 45 | ) 46 | ); 47 | } 48 | 49 | function getModules() { 50 | // Check if TypeScript is setup 51 | const hasTsConfig = fs.existsSync(paths.appTsConfig); 52 | const hasJsConfig = fs.existsSync(paths.appJsConfig); 53 | 54 | if (hasTsConfig && hasJsConfig) { 55 | throw new Error( 56 | 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.' 57 | ); 58 | } 59 | 60 | let config; 61 | 62 | // If there's a tsconfig.json we assume it's a 63 | // TypeScript project and set up the config 64 | // based on tsconfig.json 65 | if (hasTsConfig) { 66 | config = require(paths.appTsConfig); 67 | // Otherwise we'll check if there is jsconfig.json 68 | // for non TS projects. 69 | } else if (hasJsConfig) { 70 | config = require(paths.appJsConfig); 71 | } 72 | 73 | config = config || {}; 74 | const options = config.compilerOptions || {}; 75 | 76 | const additionalModulePaths = getAdditionalModulePaths(options); 77 | 78 | return { 79 | additionalModulePaths: additionalModulePaths, 80 | hasTsConfig, 81 | }; 82 | } 83 | 84 | module.exports = getModules(); 85 | -------------------------------------------------------------------------------- /src/util/distance.ts: -------------------------------------------------------------------------------- 1 | export function getChar() { 2 | let c: string[] = []; 3 | for (let d in dist) { 4 | c.push(d); 5 | } 6 | return c; 7 | } 8 | 9 | export const dist: Record = { 10 | //Front Line 11 | Rima: 105, 12 | Miyako: 125, 13 | Kuuka: 130, 14 | Jyun: 135, 15 | OedoKuuka: 140, 16 | Kaori: 145, 17 | NewRei: 153, 18 | //ShibuRin: 154, 19 | Pekorinne: 155, 20 | //PrincessPekorinne: 156, 21 | Ruka: 158, 22 | //NewKokkoro: 159, 23 | Nozomi: 160, 24 | Muimi: 162, 25 | Makoto: 165, 26 | //Kaya: 168, 27 | NewHiyori: 170, 28 | OedoNinon: 175, 29 | Akino: 180, 30 | SummerMakoto: 181, 31 | Matsuri: 185, 32 | //Chloe: 186, 33 | ValentineEriko: 187, 34 | ChristmasAyane: 190, 35 | Tsumugi: 195, 36 | Hiyori: 200, 37 | Misogi: 205, 38 | Ayane: 210, 39 | //HalloweenMisogi: 212, 40 | Tamaki: 215, 41 | Tomo: 220, 42 | //Chieru: 222, 43 | SummerTamaki: 225, 44 | Eriko: 230, 45 | SummerPekorinne: 235, 46 | Kurumi: 240, 47 | Djeeta: 245, 48 | Rei: 250, 49 | //ChristmasIlya: 255, 50 | //ChristmasChristina: 265, 51 | Shizuru: 285, 52 | Christina: 290, 53 | ChristmasKurumi: 295, 54 | 55 | //Middle Line 56 | Mimi: 360, 57 | Shinobu: 365, 58 | //HalloweenMimi: 366, 59 | //Uzuki: 370, 60 | ValentineShizuru: 385, 61 | Mahiru: 395, 62 | Yukari: 405, 63 | Monika: 410, 64 | Ninon: 415, 65 | //ChristmasNozomi: 418, 66 | Mifuyu: 420, 67 | Ilya: 425, 68 | SummerKaori: 426, 69 | Saren: 430, 70 | Anna: 440, 71 | HalloweenShinobu: 441, 72 | SummerMifuyu: 495, 73 | Kokkoro: 500, 74 | Ayumi: 510, 75 | Glare: 525, 76 | SummerKokkoro: 535, 77 | Rem: 540, 78 | Ram: 545, 79 | Rin: 550, 80 | Mitsuki: 565, 81 | Akari: 570, 82 | Yori: 575, 83 | SummerSaren: 585, 84 | HalloweenMiyako: 590, 85 | 86 | //Back Line 87 | Arisa: 625, 88 | Ann: 630, 89 | Rou: 640, 90 | Neneka: 660, 91 | //TransferAoi: 680, 92 | //NewKyaru: 690, 93 | //Mio: 695, 94 | Rino: 700, 95 | Suzuna: 705, 96 | SummerSuzuna: 708, 97 | Shiori: 710, 98 | //MagicalShiori: 712, 99 | Io: 715, 100 | SummerIo: 717, 101 | Suzume: 720, 102 | //NewSuzume: 721, 103 | Emilia: 722, 104 | Kasumi: 730, 105 | //MagicalKasumi: 731 106 | Misato: 735, 107 | Nanaka: 740, 108 | NewYui: 745, 109 | Kyaru: 750, 110 | Hatsune: 755, 111 | Misaki: 760, 112 | //Luna: 765, 113 | ChristmasChika: 770, 114 | SummerSuzume: 775, 115 | SummerKyaru: 780, 116 | Aoi: 785, 117 | Chika: 790, 118 | SummerMaho: 792, 119 | Maho: 795, 120 | Yui: 800, 121 | Yuki: 805, 122 | //Yuni: 807, 123 | Kyouka: 810, 124 | HalloweenMisaki: 815, 125 | //HalloweenKyouka: 820, 126 | }; 127 | -------------------------------------------------------------------------------- /src/util/prime.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var prime = require('nth-prime'); 4 | var primeChar = { 5 | //Front Line 6 | Rima: prime(1), 7 | Miyako: prime(2), 8 | Kuuka: prime(3), 9 | Jyun: prime(4), 10 | OedoKuuka: prime(5), 11 | Kaori: prime(6), 12 | NewRei: prime(7), 13 | Pekorinne: prime(8), 14 | Ruka: prime(9), 15 | Nozomi: prime(10), 16 | Muimi: prime(11), 17 | Makoto: prime(12), 18 | NewHiyori: prime(13), 19 | OedoNinon: prime(14), 20 | Akino: prime(15), 21 | Matsuri: prime(16), 22 | ValentineEriko: prime(17), 23 | ChristmasAyane: prime(18), 24 | Tsumugi: prime(19), 25 | Hiyori: prime(20), 26 | Misogi: prime(21), 27 | Ayane: prime(22), 28 | Tamaki: prime(23), 29 | Tomo: prime(24), 30 | SummerTamaki: prime(25), 31 | Eriko: prime(26), 32 | SummerPekorinne: prime(27), 33 | Kurumi: prime(28), 34 | Djeeta: prime(29), 35 | Rei: prime(30), 36 | Shizuru: prime(31), 37 | Christina: prime(32), 38 | ChristmasKurumi: prime(33), 39 | //Middle Line 40 | Mimi: prime(34), 41 | Shinobu: prime(35), 42 | ValentineShizuru: prime(36), 43 | Mahiru: prime(37), 44 | Yukari: prime(38), 45 | Monika: prime(39), 46 | Ninon: prime(40), 47 | Mifuyu: prime(41), 48 | Ilya: prime(42), 49 | Saren: prime(43), 50 | Anna: prime(44), 51 | HalloweenShinobu: prime(45), 52 | SummerMifuyu: prime(46), 53 | Kokkoro: prime(47), 54 | Ayumi: prime(48), 55 | Glare: prime(49), 56 | SummerKokkoro: prime(50), 57 | Rem: prime(51), 58 | Ram: prime(52), 59 | Rin: prime(53), 60 | Mitsuki: prime(54), 61 | Akari: prime(55), 62 | Yori: prime(56), 63 | HalloweenMiyako: prime(57), 64 | //Back Line 65 | Arisa: prime(58), 66 | Ann: prime(59), 67 | Rou: prime(60), 68 | Rino: prime(61), 69 | Suzuna: prime(62), 70 | SummerSuzuna: prime(63), 71 | Shiori: prime(64), 72 | Io: prime(65), 73 | SummerIo: prime(66), 74 | Suzume: prime(67), 75 | Emilia: prime(68), 76 | Kasumi: prime(69), 77 | Misato: prime(70), 78 | Nanaka: prime(71), 79 | NewYui: prime(72), 80 | Kyaru: prime(73), 81 | Hatsune: prime(74), 82 | Misaki: prime(75), 83 | ChristmasChika: prime(76), 84 | SummerSuzume: prime(77), 85 | SummerKyaru: prime(78), 86 | Aoi: prime(79), 87 | Chika: prime(80), 88 | Maho: prime(81), 89 | Yui: prime(82), 90 | Yuki: prime(83), 91 | Kyouka: prime(84), 92 | HalloweenMisaki: prime(85), 93 | //additional char 94 | SummerSaren: prime(86), 95 | SummerKaori: prime(87), 96 | SummerMakoto: prime(88), 97 | SummerMaho: prime(89), 98 | Neneka: prime(90) 99 | }; 100 | exports["default"] = primeChar; 101 | -------------------------------------------------------------------------------- /src/util/distance.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | function getChar() { 4 | var c = []; 5 | for (var d in exports.dist) { 6 | c.push(d); 7 | } 8 | return c; 9 | } 10 | exports.getChar = getChar; 11 | exports.dist = { 12 | //Front Line 13 | Rima: 105, 14 | Miyako: 125, 15 | Kuuka: 130, 16 | Jyun: 135, 17 | OedoKuuka: 140, 18 | Kaori: 145, 19 | NewRei: 153, 20 | //ShibuRin: 154, 21 | Pekorinne: 155, 22 | //PrincessPekorinne: 156, 23 | Ruka: 158, 24 | //NewKokkoro: 159, 25 | Nozomi: 160, 26 | Muimi: 162, 27 | Makoto: 165, 28 | //Kaya: 168, 29 | NewHiyori: 170, 30 | OedoNinon: 175, 31 | Akino: 180, 32 | SummerMakoto: 181, 33 | Matsuri: 185, 34 | //Chloe: 186, 35 | ValentineEriko: 187, 36 | ChristmasAyane: 190, 37 | Tsumugi: 195, 38 | Hiyori: 200, 39 | Misogi: 205, 40 | Ayane: 210, 41 | //HalloweenMisogi: 212, 42 | Tamaki: 215, 43 | Tomo: 220, 44 | //Chieru: 222, 45 | SummerTamaki: 225, 46 | Eriko: 230, 47 | SummerPekorinne: 235, 48 | Kurumi: 240, 49 | Djeeta: 245, 50 | Rei: 250, 51 | //ChristmasIlya: 255, 52 | //ChristmasChristina: 265, 53 | Shizuru: 285, 54 | Christina: 290, 55 | ChristmasKurumi: 295, 56 | //Middle Line 57 | Mimi: 360, 58 | Shinobu: 365, 59 | //HalloweenMimi: 366, 60 | //Uzuki: 370, 61 | ValentineShizuru: 385, 62 | Mahiru: 395, 63 | Yukari: 405, 64 | Monika: 410, 65 | Ninon: 415, 66 | //ChristmasNozomi: 418, 67 | Mifuyu: 420, 68 | Ilya: 425, 69 | SummerKaori: 426, 70 | Saren: 430, 71 | Anna: 440, 72 | HalloweenShinobu: 441, 73 | SummerMifuyu: 495, 74 | Kokkoro: 500, 75 | Ayumi: 510, 76 | Glare: 525, 77 | SummerKokkoro: 535, 78 | Rem: 540, 79 | Ram: 545, 80 | Rin: 550, 81 | Mitsuki: 565, 82 | Akari: 570, 83 | Yori: 575, 84 | SummerSaren: 585, 85 | HalloweenMiyako: 590, 86 | //Back Line 87 | Arisa: 625, 88 | Ann: 630, 89 | Rou: 640, 90 | Neneka: 660, 91 | //TransferAoi: 680, 92 | //NewKyaru: 690, 93 | //Mio: 695, 94 | Rino: 700, 95 | Suzuna: 705, 96 | SummerSuzuna: 708, 97 | Shiori: 710, 98 | //MagicalShiori: 712, 99 | Io: 715, 100 | SummerIo: 717, 101 | Suzume: 720, 102 | //NewSuzume: 721, 103 | Emilia: 722, 104 | Kasumi: 730, 105 | //MagicalKasumi: 731 106 | Misato: 735, 107 | Nanaka: 740, 108 | NewYui: 745, 109 | Kyaru: 750, 110 | Hatsune: 755, 111 | Misaki: 760, 112 | //Luna: 765, 113 | ChristmasChika: 770, 114 | SummerSuzume: 775, 115 | SummerKyaru: 780, 116 | Aoi: 785, 117 | Chika: 790, 118 | SummerMaho: 792, 119 | Maho: 795, 120 | Yui: 800, 121 | Yuki: 805, 122 | //Yuni: 807, 123 | Kyouka: 810, 124 | HalloweenMisaki: 815 125 | }; 126 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebook/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | const envPublicUrl = process.env.PUBLIC_URL; 13 | 14 | function ensureSlash(inputPath, needsSlash) { 15 | const hasSlash = inputPath.endsWith('/'); 16 | if (hasSlash && !needsSlash) { 17 | return inputPath.substr(0, inputPath.length - 1); 18 | } else if (!hasSlash && needsSlash) { 19 | return `${inputPath}/`; 20 | } else { 21 | return inputPath; 22 | } 23 | } 24 | 25 | const getPublicUrl = appPackageJson => 26 | envPublicUrl || require(appPackageJson).homepage; 27 | 28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 29 | // "public path" at which the app is served. 30 | // Webpack needs to know it to put the right