A suite to track Project Diva score statistics and ratings / D4DJ event data.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
projectdivar/frontend/src/App.js

1600 lines
142 KiB

import React, {useState,useEffect,useRef} from 'react';
import logo from './logo.svg';
import './App.css';
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useRouteMatch,
useParams,
useHistory
} from "react-router-dom";
import {
Modal,
Button,
Form
} from "react-bootstrap";
const REMOTE_ADDR = "http://45.33.13.215:4502";
const axios = require('axios');
var IMAGE_CAMERA=(p)=>{
return(
<svg {...p} width="1em" height="1em" viewBox="0 0 16 16" className="bi bi-camera-fill link cursor" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5 8.5a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z"/>
<path fillRule="evenodd" d="M2 4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-1.172a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 9.172 2H6.828a2 2 0 0 0-1.414.586l-.828.828A2 2 0 0 1 3.172 4H2zm.5 2a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1zm9 2.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0z"/>
</svg>
)
}
var RATING_cool=new Image();
RATING_cool.src="data:image/png;base64,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
var RATING_fine=new Image();
RATING_fine.src="data:image/png;base64,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
var RATING_safe=new Image();
RATING_safe.src="data:image/png;base64,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
var RATING_sad=new Image();
RATING_sad.src="data:image/png;base64,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
var RATING_worst=new Image();
RATING_worst.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGMAAAAVCAYAAABSQFBJAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AYht+mSkVaHOwg4pChOlkVFXGUKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjxjuMe3vvel7vvAKFRYarZNQGommWk4jExm1sVA68IIERzDOMSM/VEejEDz/F1Dx/f76I8y7vuzxFS8iYDfCLxHNMNi3iDeGbT0jnvE4dZSVKIz4lHDbog8SPXZZffOBcdFnhm2Mik5onDxGKxg+UOZiVDJZ4mjiiqRvlC1mWF8xZntVJjrXvyFwbz2kqa67SGEMcSEkhChIwayqjAQpR2jRQTKTqPefgHHX+SXDK5ymDkWEAVKiTHD/4Hv3trFqYm3aRgDOh+se2PYSCwCzTrtv19bNvNE8D/DFxpbX+1Acx+kl5va5EjoG8buLhua/IecLkDDDzpkiE5kp+WUCgA72f0TTmg/xboXXP71jrH6QOQoV4t3wAHh8BIkbLXPd7d09m3f2ta/fsBxMxyyECtw/8AAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfkBw0VBjf1QZTrAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAEh1JREFUaN6dmVmMZNV5x3/n3Fv33lq6lu7q7ulllp4VMAy2MWNsYLABJ3awFMUPUeJIkZK3JFKezZOVp/glyiNKojzkIX6JIkeJiB0jO3bABgwEzAxmzCzM9Mz09FLdtVfd5Zzz5eFW1zQGL8op1dKte79zvu3//b/vqovvXuD61Rv02gOMM4gI1loKYYEjJ1eZby6ws9mivdUhS1MQEMDzFI35WdaOHwNleevNC2xt7NSsdYsASqm4NFNeP3n6BNVmlTRO2drcYWerRTyKMUZqBEG3UCojhQLWgUPhUABECI1GjZXDSxxbnqcaFdnc2OTG1XW6vT7OOQCUgJ7cs78cwuQMiIKCp6nXqhw+ukK0coiBUozGY0abW3S29tjd3qXX7ZEkae2gnA9Kvbu0p7uNep3mQpOdrR06e92aU5IghJLvm/Ar1+R8osIwKnQXl5dYPrqEf/mVm/z7P39H9m73sOJQKAShGEXc98gpjh478uw7P333r9cvbZClBrEOQeF5irnVGk9/6cnH++PO0y+/8ObXtzd2EAuCoBTMNGb4zJPJ9oNP3ru4/s7GY2+9euHFW9c2GPUSnLU4rRGtsYC4/WPmJij4HnOHZjn5seM88uQD6vSJE/zw2y/96Yv/8eo/dna7OMl1Und1+2grKoXnezSaNe7/xD2c/MJZtfLgaQa9Pu/98B2uvHZVbl25Tb/dJx6nKJEPC1L5Fkok181TzM03WFlb4fZ7t9m70wanpteLfMSZfskRvZLi5MMneOIPHlPqb/7i7+Wlf3ud+45+nGKxOBV0+/ZtNkbXUL6gMo+1xTPM1puI5GKMSbhw7XUai1W29u6wFJ1gZeEIvu8DCucMt7dvsT28zZnzR1n/6RZFqdCsHqJcmJlG7cFgOfinVUJ72GZj7xazJ0IefuQTz7/147efGb/vWDl0lMAP9+OLX7eMM/TjPju9W8gpjye/+juq3+nx0j99R/xuyELlENVijcCPwMldiUpNv5UCnOBEGCdD3r18kb3RHnNqniOzRymYABGFuNwZIoJIDiMiuUxxkts3dy2CZTPeYDjX4am/PP+sH1BitnyIT3/yPIdX1qbpf/HiRb79vQ43br3P/SfPcv7TX2R1eQ2FBgXGjEjTlLfefpM4Fs5++RznHvoshUKIUpo4HfLij/6bK99/n4vfusGJw/fw+GOfZ3FhhWJYQinv1ySyZTDq8d61n/Hyy//NC5d/9IzJDA+fepRHH/k8pWIFEfLzoH+1M6xhOOpx5do7/ODCD/jBP3xPlIXZ1iLnHv4sJ46doViYwfcKU3jLf3gIgsssLrOYJMOmhr3ONq3rbbrDEcvVYzyy+gTFcQ1nVI4MThAriDiUgDgHThDL1DlYSL2Yt9M3eKf7Klkv+zO/vjjzzZEdfHW7tcvywun8QoRKuUpxpojZcdTqs1QrdXA+TvIoUQQszh9B+z9DJKZUrIGEOFMABaNhzJ2tDWKX0Cwvcv7xL3B4ZQ1rwBof7eu7Sn8ogQURj0qpyQP3nGN7Y5sXX/k+RlnMcYUTH+cKiKipjA/JEsBNIFM05ajBvac+yc7eNj/8nxcoVyo89MQXue/0pyjoIjiNy0CZ3GhZnKGSDBs70mFGOjRkI4OLLb1hivR8PDz0KEB3Qgr9IliFsznkKpsHlAiIyTNEuQkcO4VYi/OFQhqgSqAUiV+brT5rMV/tdNp58XOC0lAqlYmiCA+ferVBMSpP0i83mMKnObdAMSqRjEeEYQSi8vsVDEdDWrvbIIZ6pcry0gqQ4zfkDvU8hVIyRQOUwlqHyfIU9zxNwS/QaDQJooA07mOtQ6xMHSciKC34voc6kCDiFCZzOONQSqGUh+8H1Gs1RAsFHdCIZvFinyyxZKMUE6dI6hAjpOMEGVts7DCxQ7LciEocNs2JjgbEWrI0ITMpyiqcFcQAGbCfCS6vNTJJDREFIlgxOCyS15nQn2lU1sNSQH/QJTMZWnmIQKVSpT7ToBY2qFVnCYIIZ/XUCEppZmbqlMIKUssoFcvT6DTW0O12GcYDtFIEvo/vB4jTU4zvDzpsbm4wGvanEQSKueYCS4tH8TwfcaC1JgyLUwjJ71fsFxznHN3OLht3bpKm46n8oBBxaPEwc4356bWIQotCoXCJo7PZZzPbRsYaM3Zko4Rer0O/10OsoA141suLs+g8qpWh7zrEyQjP18RuyI2Na1SSDkoUDihIQEPVCVw4qQ2CxTKky4A+OQVSJFlCT3qExYgoil7yKVoah6oknRFZlhAEZUARhiWqtVmWFpap12ZRykPEkmUW7Xl4BcVMqUy1MkMYeYRhSB6aCmMzdne3EGspRxWUKiDOm2B7nhXt3jYvv/F9Nrdv4Qc+JrOkScaD9z9Ec24eX89MeGpuwH3KKspNIklN3sLG9nVeePE/aXe3UcpDOWG2usD5R55mtlInS4RknJAMh3S2u4gRrBVG6xnxboqfBGirwFqu713iSv/nGLIJ1u1noUbhkZvbUp4t8ZmHztG+1uO9GxfwbAQIKSkVajwgDzHLPB4+gpCRcYNrXOcqgiEkxInF1Sz3fupejp458kd+VPdprtbZ3RoxGPSYaxbzjbWmWm6wtHiEmXIdcYrMGPbaLSqVCjNBlSAoMVNqUPVrFPxoyvLTJGZvr0VQDig3IryC9wtVIWdbYzvg6NlFHv3Kp9i+0eHlF95gNO7jnOE3WTJR05gx47jPMO7jSZ5BRRkxvDlgoEakQ0sWG5LBmE6rm8MNCq+n8IyHNh7iBKxDWfDwEOwH9tnXzUpKwhilDPoE3H/+zHPGmkXlvJoZmqcuvXiZ1pu7jNIBdWYnsgSHpccuSaPPfU+dZOn04rouqMt+yX9+bm32b5un5/Dnj8xx+NTyN269/LOvdbst5hcWcC6nXrXqHCx5lKIZnBPSdMTGnXWWl5epVut4XkBzbpEg8gkKB5yRjegNu1QbZYJiAc98NNvxA82Jj63xpT8+r95/c5P1K7cku+GhlJ7UkUmBPlCctUDBgZcKLnG4sdDIFnhk5XGGtT7a+DgLRV2k2m/QuzJAMoUTy95whzutW5NGUSNJbmhnLOIETcCKd5yZcA6rDNru1x83gUSLVSl96bLRvcnFH7/D4T9Z/eYnH3/wJR14xO2Ezp2O7F5sY1ODm7SfbuIMgyEsFzh17sSf3/PU6ef8UCNKEA+sZ/FVAPWF6rMqkK/tdlucONCx1CuzhF6ZMCgCkKQj7txZp1KJWF46iqd8Di2u4vkK3y+AgMORZGMsKfPLcwxG/ZzSfbgBBQXKV1DUSGDJtb/L7XOsFrCCEoWykPZi2uu7DCUmG1oYKfykzAn/Y7iSzZ3hHNppdOqjRh5
function Logo(){
var note_arrow=new Image();
note_arrow.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAABjCAYAAACWsFAzAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AYht+mSkVaHOwg4pChOlkVFXGUKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjxjuMe3vvel7vvAKFRYarZNQGommWk4jExm1sVA68IIERzDOMSM/VEejEDz/F1Dx/f76I8y7vuzxFS8iYDfCLxHNMNi3iDeGbT0jnvE4dZSVKIz4lHDbog8SPXZZffOBcdFnhm2Mik5onDxGKxg+UOZiVDJZ4mjiiqRvlC1mWF8xZntVJjrXvyFwbz2kqa67SGEMcSEkhChIwayqjAQpR2jRQTKTqPefgHHX+SXDK5ymDkWEAVKiTHD/4Hv3trFqYm3aRgDOh+se2PYSCwCzTrtv19bNvNE8D/DFxpbX+1Acx+kl5va5EjoG8buLhua/IecLkDDDzpkiE5kp+WUCgA72f0TTmg/xboXXP71jrH6QOQoV4t3wAHh8BIkbLXPd7d09m3f2ta/fsBxMxyyECtw/8AAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfkBw0TDjpHpB7sAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAfVJREFUWMPtlr9q21AUxr8j7CuERQ0lUzA0gzw0VgzxliV5Bs15kA4tWQN5Db9AwG+gxdiDwe6fJc3gKTWdTDRK/jL0KpVry5KSDi2+P7hwOTrn49xzrg4XKOarXjux8j7UarW3AAjgi17UtmocHb37CIDT6ZSz2YwAqG3lOD5+LwCu6vU6ARxQA+BA2660TzGu22AQBA9JkpDkiuQqSRIGQfDgug2WTYoAHkmec5NzAI/aJx/f71yLCIfD4Zw5jEaj7yJC3+9cbwi0Wi0BcGFZFgFcxnGcp8M4jgngUvte6NjfOI5Dz/Putf+K+axIst1u3zuOs35EEblTSpHkIctzqJSiiNyldbmxbZvj8fjTNm9d2K1Kk8nkg23b9P3OTdqlW93qSkK6XrcAKAAoIvgVo/uf2YtIri3dk4TV7Z6cKqXOMneoyn2DUuqs2z05TaUlPULFjCSNtV6QydbMLPwljJARMkJG6F8RqhU5DAaDUkKybWxm5/PWoPWZvS9d+wZg+YL4pY59Fmo0m803VVV0TGOt/cvlsrBbf74Nsm+Aff1FsjUouvE7M/I8D2EYIgxDeJ73up92sVi8/mi9Xg/9fv95X4Z53oNzF3pazPdlZruuCxGptFzX3eja5yiKflbNIooiAPgBg8FgMBgMBoPBYPjfeQJefdQWdKdLVQAAAABJRU5ErkJggg=="
var note_circle=new Image();
var note_circle_shadow=new Image();
var notes=[new Image(),new Image(),new Image(),new Image()]
notes[0].src="data:image/png;base64,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
notes[1].src="data:image/png;base64,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
notes[2].src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAABHCAYAAABcW/plAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AYht+mSkVaHOwg4pChOlkVFXGUKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjxjuMe3vvel7vvAKFRYarZNQGommWk4jExm1sVA68IIERzDOMSM/VEejEDz/F1Dx/f76I8y7vuzxFS8iYDfCLxHNMNi3iDeGbT0jnvE4dZSVKIz4lHDbog8SPXZZffOBcdFnhm2Mik5onDxGKxg+UOZiVDJZ4mjiiqRvlC1mWF8xZntVJjrXvyFwbz2kqa67SGEMcSEkhChIwayqjAQpR2jRQTKTqPefgHHX+SXDK5ymDkWEAVKiTHD/4Hv3trFqYm3aRgDOh+se2PYSCwCzTrtv19bNvNE8D/DFxpbX+1Acx+kl5va5EjoG8buLhua/IecLkDDDzpkiE5kp+WUCgA72f0TTmg/xboXXP71jrH6QOQoV4t3wAHh8BIkbLXPd7d09m3f2ta/fsBxMxyyECtw/8AAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfkBw0VOy+MxUQDAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAA5tJREFUeNrtnM9rE0EUx79vN7EVAgaDVy9aQfHYa1s8e/FQeiiePXjTU72WgkchIL3rxSoKgkjBHpQg0j+gVkqVYC45VEJN2t3szs7zMNlk06YtbXbrTnYehNn8YNj3me9783ZmCK2svHoKyHEwjwHyEsDjAI+p9qxm7XZbsnYBcgFC2mx2dvaJZVnd9wSAkVHzvDbl8/neEMJY13LhxdT1KSzdW0r1zbLnQv7ZAfkEEgQKAMjT9fF84yVe//p4PIxSoYTpiel0w3CaCC7WQW2C5RMooFPDeF/9dHSm00nGHAgQh6k4/oSsFwzfU+mek0n7Oa0yXAQGYXgg1WoVuVxOTxjs+yAmgCkWZaytrbFt2/qFCQsP8IP+MOGM5gxu7wMSIAlQQmWiNjCk0wLJuFXR35EeOUMGwL4DSFKvuJTBPsCyownSA4Z0W6q4CkOEKWZlBJqECTN4rwUS6IZJUs+/qYfBfhvseoAkkOyU3wkl0KHCpP63jsUPi4lPqew4IIEuCGKljYe37uP25RvpgNHYa2D5y/J/U83dq3eGhJHrBIeirFc5HreRrV6dZBobjPn5eczMJL8EsLHxHeVyOQkyZqVL20d4A8PAMDAMjDRZYnVGsVh8Njc39zjufldXVyfK5fKWUYYJEwNjtHKGDiZZLRYxq3I80zCEIEgmvZQRXcthTqbfVMHgyAVHHGdWclYtwRPU1j5ncMS56DVAhz7jYxQgEzxaEyuM0BEwEEjAE1EHqe97HqTTUZlNhAQ80UtGfkBtT5BWh6SsxLIRQ7vTYrmzxAIHAvBdyFZjVIsuPhD8DOYAkIFyXvjqsIjnASIABxK829S7/LYA21abUhSFIZ19iNr2YTaRjd7uxq8ELAkkN8mdj+VtwLYGKIMCBjlHxz11oVBnIwcgcU4HXakzetR/88mFiSSQRwMTIw1USue0XYwOW6QcDluKQKDOb/L2ecBgqC28gbMEDT5DxSeMJh0e2dCxqMNApI38fmC3dA4wiDHcSEdGNBzB8Qu9kc7UI/y3rxVsb/3oJad8fuHd2zcLcd9wvV5PP4xarYZardb32fr6ul5TLYzFo4ybxWvgBz9HBoZRhoFhYBgYBoaBYWAYGAaGgWFgGBipelD7+PszrryYHHmH94RzMgxP+thxG9lWxuRkvxqazSZc182E83RgQZX4wHZ3pVLB5uZmJv9GwiRQA8PAMDAMjGGLrtAKhQJKpdKjLML4BwfkgOBZ+ypaAAAAAElFTkSuQmCC"
notes[3].src="data:image/png;base64,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
var shadownotes=[new Image(),new Image(),new Image(),new Image()]
shadownotes[0].src="data:image/png;base64,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
shadownotes[1].src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABKCAYAAAAG7CL/AAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AYht+mSkVaHOwg4pChOlkVFXGUKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjxjuMe3vvel7vvAKFRYarZNQGommWk4jExm1sVA68IIERzDOMSM/VEejEDz/F1Dx/f76I8y7vuzxFS8iYDfCLxHNMNi3iDeGbT0jnvE4dZSVKIz4lHDbog8SPXZZffOBcdFnhm2Mik5onDxGKxg+UOZiVDJZ4mjiiqRvlC1mWF8xZntVJjrXvyFwbz2kqa67SGEMcSEkhChIwayqjAQpR2jRQTKTqPefgHHX+SXDK5ymDkWEAVKiTHD/4Hv3trFqYm3aRgDOh+se2PYSCwCzTrtv19bNvNE8D/DFxpbX+1Acx+kl5va5EjoG8buLhua/IecLkDDDzpkiE5kp+WUCgA72f0TTmg/xboXXP71jrH6QOQoV4t3wAHh8BIkbLXPd7d09m3f2ta/fsBxMxyyECtw/8AAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfkBw0WAQQHlt1jAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAABzBJREFUeNrtnFlzFFUUgL/uhMTCgKjDZgISIQVRI4hVIJQWi2XJJi5oUfKgTz5Z5Z/wX7hgqZSWCykX5AEF2UqFElkClYBIIpDEQAIRUiAgjA/3XLxcenp6m57N8zKZmXT36a/PPefcc88dh4Aya9aL5ttTwFPAMYCurnaKKZZuWcDRb6Lq5ka48C9AE3AUmEaRxQOK+Wp/H1ickBfeBTxhPZlmoKcYlmPoVgeMAKOMr68BDcDVKLq5AS/sAlsMKBpqFugGZsR5OjGhjAGGLCjI+yH5PrRuboAL1wNfAk+bJmpZ3G/Ag2nBMa6RAU6IZXhJg3yfCaubm+fCdwIbgGdtp+YhR4C5crxTQCj63I3Afn3TPpKR/2sMo5vrA6UBeA94KQAULfuAhUC2EHDknFlx+tslCASRJvn/aUF1c30s5W1gbQgoWnYDS5KGY0CZAWyW12zAw287Lp9urgeUO8RSXokARfudzcAzScExoLQA7UBrSN308a1yfEs+3WosKDXAJ8DLEaFoqQWeAw4BxzKZVmdwsDMJS9kIPBLjgWWBicAi4HvgXC7dHMtTfx3Q0QaVYeBV4BvA6epqz4aEov9sBr4C2hLQTR/fIQ+v2yvPMX3MloShAIwDPgBWhR1WBpRG4NuEoJiW0ybnbfQK5RrMTiNPSTqa3A18BCwLCsfKU3ZE8ClhfM4OrzzHBX4Cngw6RYhhOZ8DS/PBsdKF/cD0AummzzddrtNgXt8FHg8R9uJIg0Qrnef4QamVjLWJdKQJGAQmmBbzQAEtxZZ6yXMezZOiDwHjU56orwLOmmBO2lP1AosD/ArMMuEYkC4DY4tQwegyGehwPQEYKIIyN0sWRqmgtojlnQwwdOnSeTWEBM5koK8IytwH9JcAFC13ARfMPKZfzHxuyor0iQmXAhSAv4AGxyMqzAP2UOXi8r94ySkvMJdRqwB9VQqlB5jqBaYDmAo8L5PAapIuiZTeiZ0x1V8os9pMBcPQc7CDwBxfHyPlAQf4EVXaPFPhUPYA8437V4UqLxkc7CSTaXVkzO0DlqNKnpUGZbfM/C+ZdZkavyMNON0CZyUwuoKgbAdekNzllmJVoMmj4XMWodaYxlUAlG2ouvYZG0qoGoflkL8rU8vRUH4QKANeUEIXfww4j4nDqilDKLuANbrEkGtNO3QdxoDzsOQ85RZ9VgDn/KBEAmPVTmag1q3LQQ6iSrgX80GJDMaCM4X/il2lKkdR61GBW0JilTStJd2REoVyErjfTN7SnF33lyiUM1GgJDWULpK7P6WYMoxa0woNJWpUMt+eL9FkbwTppIra/ubEgDKAsQ5TYuLEgRLKx1hQ/ihhKOghFKftLWw7a50Uc6aWeHg+h2r3iAzHDQFlDLAXmFkmCd2f+gFGgRO0nfUemTjOJr0VyyTkOKp7KnTDZJB21vFSaphPYdpECimjUHWkNkL25+RrZ50IfCpzjHKDYrqAbaiFxGwS7awTgI+RDswyhaIlA2xCLSYGguP4+JSNwOIKgGLKaVRxfw95egKdHNFnM2rfQCVB0fdySuDs9YPjWFDqUT1p8ysMig3nNGpBcV8uOHY76wEjJFcaFBtOP6pJu8Nr+mA6306BQgVDMe9tMqoo3uKVBGow3UjrV5XJvTKcpthwdA/eNKpXxkiGfEuvr6tpVbnUoZZTJocuO1SBzMYo0brcvpewmPKPOEenCD7vihmddLiuB/4uoYhhPsUDKV5/Oqoj/eZQukJxmo5NuaCfmJFTHEQ1EqSV3/yuA5FrKHFRJo5XiwBlCNVfe1MMvbLAjZSsVW+XbnYtJc4aSV5a0qdDZY7i9S4pe1xJEc4J1+MJQToLaIclHc+ZLohOuuVtBemsdjrAz17hugvVA9NdoHGMjOWlqPXkGz7WYvYDbkPt1Sx0J+lOYMFtcyIjLV6N6thMakKpz9OJ2k3X6wfEQy9t5quADzFWGROeXDqeCZ6haA9qF6xD/AK4uUFzZVgoluVsAl5DrYImDeUz1PZq744oaUgcQG3BXQxMimE5+rhDqE6mE1IDCX0io1nyqAz1w6gdeqMSgLIBWCdJJk4A020BvhB/EMdS1qCajEJvM/bRDVTXZXtMKOuB101/5wRUYA7q1z7eQm0VDOtTVssMNjaUHPotR5Vjo0B5F3gDq6nICfl0ZqJ6YycFvPhxcbQ9SUPx0G+JRK6gQADeAd7U06HQfb6WAs3AVnn1k9My/nsLBcUjki6QnCefrAfeFx817BUIApcdjBvrDnDcIGqnbK91bEHEuKmfUK225Iik+rNeVKv8cK7oGLVxaKyc3KuTagS1zzFQd2SBLKdNoqA5bMyQvA647qdb1ELVBVS99Jr1+TX5PHUo1sy8A9WHbPpHB/XjG2uB6/nO5cYw26uokqApdUT8FbECyBFJMbTFbJXoSBD9kmhOrLUqcEWHUlMzmpaWZfrtPHG0DwWFAvAvzCNgJXud89YAAAAASUVORK5CYII="
shadownotes[2].src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABKCAYAAAAG7CL/AAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AYht+mSkVaHOwg4pChOlkVFXGUKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjxjuMe3vvel7vvAKFRYarZNQGommWk4jExm1sVA68IIERzDOMSM/VEejEDz/F1Dx/f76I8y7vuzxFS8iYDfCLxHNMNi3iDeGbT0jnvE4dZSVKIz4lHDbog8SPXZZffOBcdFnhm2Mik5onDxGKxg+UOZiVDJZ4mjiiqRvlC1mWF8xZntVJjrXvyFwbz2kqa67SGEMcSEkhChIwayqjAQpR2jRQTKTqPefgHHX+SXDK5ymDkWEAVKiTHD/4Hv3trFqYm3aRgDOh+se2PYSCwCzTrtv19bNvNE8D/DFxpbX+1Acx+kl5va5EjoG8buLhua/IecLkDDDzpkiE5kp+WUCgA72f0TTmg/xboXXP71jrH6QOQoV4t3wAHh8BIkbLXPd7d09m3f2ta/fsBxMxyyECtw/8AAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfkBw0WAROERVikAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAQ1JREFUeNrt2r0KglAcQPGjFATR2BSt4Ri0NfcE9ZrRG/QGQWvQ7NQLBH3YkESZW2aa54x3uMgPvcP/GkTRPMH2wGi3Wz0WQk3yE0YYYYQR5ge1JADgAhBFc2EyDYHls4cw97rAwjPGw1cYYYQRRhhhhBFGGBNGGGGEEUaYylXGBG8AHIGgoP0SoAPEdYc5AKeC92z/wxsTAjxfmH9SOskPS3loE0YYYYQRRhhhhBFGGGFMGGGEKb4y5jFXeP0jsqg96w7T5zujzdrDxHX8lDxjhBFGGGGEEUYYYYQRRhgTRhhhhBFGmCrXAtaZtTMwBXpNh5nlrG+ASZNh3ib36TXHFhh7xpgwwggjTKndAANPGt4oQR7PAAAAAElFTkSuQmCC"
shadownotes[3].src="data:image/png;base64,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"
var divar=new Image();
divar.src="data:image/png;base64,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
var logo;
var timer=0;
var startpoint = [Math.random()*1000-500,Math.random()*1000-500]
var scorepoint = [Math.random()*10-5,Math.random()*10-5]
var pos = [...startpoint];
var hitrating=-1;
var timer2=0;
var notetype=0;
setTimeout(()=>{
logo=document.getElementById("logo");
var draw = logo.getContext("2d");
draw.font="64px Open Sans Condensed";
var size=draw.measureText("Pr ject")
logo.width=size.width
setInterval(()=>{
if (hitrating==-1) {
pos[0]-=startpoint[0]/20;
pos[1]-=startpoint[1]/20;
if ((Math.abs(pos[0])<32 && Math.abs(pos[1])<32 && Math.random()*10<1)
|| (Math.abs(pos[0])<16 && Math.abs(pos[1])<16 && Math.random()*4<1)
|| (Math.abs(pos[0])<4 && Math.abs(pos[1])<4 && Math.random()*2<1)) {
scorepoint = [Math.random()*30-15,Math.random()*30-15]
var distance = Math.abs(pos[0])+Math.abs(pos[1])
if (distance>32) {
hitrating=4;
} else
if (distance>16) {
hitrating=3;
} else
if (distance>4) {
hitrating=2;
} else
if (distance>2) {
hitrating=1;
} else {
hitrating=0;
}
timer2=Math.random()*400+350;
}
if (timer>1300) {
hitrating=4;
timer2=350;
}
}
if (hitrating!=-1 && timer2<=0) {
hitrating=-1;
notetype=Math.floor(Math.random()*4)
startpoint = [Math.random()*1000-500,Math.random()*1000-500]
pos = [...startpoint];
timer=0;
}
var draw = logo.getContext("2d");
draw.clearRect(0, 0, logo.width, logo.height);
draw.font="64px Open Sans Condensed";
var size=draw.measureText("Pr ject")
draw.fillStyle="#000000";
draw.fillText("Pr ject",0,48);
draw.font="28px Open Sans Condensed";
draw.fillStyle="#FFFFFF";
draw.drawImage(divar,14,45,152,32);
if (hitrating==-1) {
draw.drawImage(shadownotes[notetype],70-19,14,36,36);
draw.drawImage(notes[notetype],70-19+pos[0],14+pos[1],36,36);
draw.save();
drawImage(note_arrow,70+22-4-19,14-19+38,0.5,((timer/50)*18)*(Math.PI/180));
draw.restore();
} else {
switch (hitrating) {
case 0:{
draw.drawImage(RATING_cool,70-19+scorepoint[0],14+scorepoint[1]);
}break;
case 1:{
draw.drawImage(RATING_fine,70-19+scorepoint[0],14+scorepoint[1]);
}break;
case 2:{
draw.drawImage(RATING_safe,70-19+scorepoint[0],14+scorepoint[1]);
}break;
case 3:{
draw.drawImage(RATING_sad,70-19+scorepoint[0],14+scorepoint[1]);
}break;
case 4:{
draw.drawImage(RATING_worst,70-19+scorepoint[0],14+scorepoint[1]);
}break;
}
}
timer+=50;
timer2-=50;
//p.setSiteCounter(p.siteCounter+1);
},50)
},300);
function drawImage(image, x, y, scale, rotation){
var draw = logo.getContext("2d");
draw.setTransform(scale, 0, 0, scale, x, y); // sets scale and origin
draw.rotate(rotation);
draw.drawImage(image, -image.width / 2, -image.height / 2);
}
return (<>
<canvas className="homelink" id="logo" width="0" height="84"/>
</>);
}
function Sort(p){
let { sort,sortOrder } = useParams();
return (
<>
<Link to={"/rankings/"+p.order+"/"+((p.order===sort)?(sortOrder==="desc")?"asc":"desc":"desc")} onClick={()=>{p.setIsLoading(true);p.setUpdateUsers(!p.updateUsers)}}>{p.label}</Link>{(sort===p.order?<>{(sortOrder==="desc")?<>▼</>:<></>}</>:<></>)}
</>
)
}
function ProfileDataContainer(p){
return (
<div className={"col-md-"+p.width+" border"} onMouseOver={()=>{if (p.setMouseOver) {p.setMouseOver(true)}}} onMouseOut={()=>{if(p.setMouseOver){p.setMouseOver(false)}}}>
<div className="row">
<div className="text-center label col-6 col-md-12">
{p.label}
</div>
<div className="data col-6 col-md-12 text-center">
{p.data}
</div>
</div>
</div>
);
}
function StatisticsPanel(p) {
return (
<>
<div className="row">
<div className="col-md-1"></div>
<ProfileDataContainer label="Play Count" data={p.playcount} width="2"/>
<ProfileDataContainer label="FC Count" data={p.fccount} width="2"/>
<ProfileDataContainer setMouseOver={p.setMouseOver} label="Cleared" data={p.cleared} width="4"/>
<ProfileDataContainer label="Accuracy" data={p.accuracy} width="2"/>
<div className="col-md-1"></div>
</div>
</>
)
}
function HitCountsPanel(p) {
return (
<>
<div className="row text-center">
<div className="col-md-1">
</div>
<div className="col-md-2 border">
<div className="row">
<div className="col-6 col-md-12">
<img src={RATING_cool.src} height="16"/>
</div>
<div className="col-6 col-md-12">
{p.user.cool}
</div>
</div>
</div>
<div className="col-md-2 border">
<div className="row">
<div className="col-6 col-md-12">
<img src={RATING_fine.src} height="16"/>
</div>
<div className="col-6 col-md-12">
{p.user.fine}
</div>
</div>
</div>
<div className="col-md-2 border">
<div className="row">
<div className="col-6 col-md-12">
<img src={RATING_safe.src} height="16"/>
</div>
<div className="col-6 col-md-12">
{p.user.safe}
</div>
</div>
</div>
<div className="col-md-2 border">
<div className="row">
<div className="col-6 col-md-12">
<img src={RATING_sad.src} height="16"/>
</div>
<div className="col-6 col-md-12">
{p.user.sad}
</div>
</div>
</div>
<div className="col-md-2 border">
<div className="row">
<div className="col-6 col-md-12">
<img src={RATING_worst.src} height="16"/>
</div>
<div className="col-6 col-md-12">
{p.user.worst}
</div>
</div>
</div>
<div className="col-md-1">
</div>
</div>
</>
)
}
function SongName(p){
//console.log(p.song)
return (
<>
{(p.song)?(p.song.english_name===p.song.name)?
<>{p.song.name}</>
:
<>{p.song.name}<br/>{(p.song.romanized_name.length>0)?p.song.romanized_name:p.song.english_name}</>
:<></>
}
</>
)
}
function CalculateBadge(difficulty) {
switch (difficulty) {
case "E":{
return "primary";
}break;
case "N":{
return "info";
}break;
case "H":{
return "success";
}break;
case "EX":{
return "warning";
}break;
case "EXEX":{
return "danger";
}break;
}
}
function FormatRating(rating) {
if (rating) {
if (rating.includes(".5")) {
return rating;
} else {
return Math.floor(rating)
}
}
}
function Difficulty(p) {
return (
<>
<span className={"badge badge-"+CalculateBadge(p.play.difficulty)}>{(p.song && p.song.rating && p.song.rating[p.play.difficulty])?FormatRating(p.song.rating[p.play.difficulty]):<></>} {p.play.difficulty}</span>
</>
);
}
function ImageDisplayer(p) {
var [zoom,setZoom] = useState(false)
//p.play
return(
<Modal
size="xl"
aria-labelledby="contained-modal-title-vcenter"
centered
scrollable
show={p.modalVisible}
onHide={()=>{p.setModalVisible(false)}}
>
{(p.play!==undefined&&p.songs[p.play.songid])?<><Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
{`${p.username}'s ${p.songs[p.play.songid].name} Play - [${p.play.difficulty}] ${p.play.percent}%`}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<img src={p.play.src} width={(zoom)?"auto":"100%"} className={(zoom)?"zoomout":"zoomin"} onClick={()=>{setZoom(!zoom)}}/>
</Modal.Body></>:<></>}
</Modal>
)
}
function Play(p) {
function GetModifiedDiff(name) {
switch (name) {
case "E":{
return "easy";
}
case "N":{
return "normal";
}
case "H":{
return "hard";
}
case "EX":{
return "ex";
}
case "EXEX":{
return "exex";
}
}
}
function GetDateDiff() {
var hours = Math.floor((Date.now()-new Date(p.play.date))/1000/60/60);
var days = Math.floor(hours/24)
if (hours<24) {return <>{hours} {"hour"+((hours!==1)?"s":"")} ago</>}
return <>{days} {"day"+((days!==1)?"s":"")} ago</>
}
function GetDateDisplay(timeStampBelow) {
var date = new Date(p.play.date);
var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
return <>{months[date.getMonth()]+" "+date.getDate()+" "+date.getFullYear()+" "+date.getHours()+":"+((date.getMinutes()<10)?"0"+date.getMinutes():date.getMinutes())}<span className={"tinytime infront "+((timeStampBelow)?"moveDown":"")}>{GetDateDiff()}</span></>
}
if (p.mini) {
return (
<>
<div className={"d-none d-md-block below border border-bottom "+((p.play.src)?"background-songs-click":"")} onClick={(p.play.src)?()=>{p.setModalSrc(p.play)
p.setModalVisible(true)}:null}>
<div className={((p.play.fine==0&&p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?"pfchighlight":(p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?"fchighlight":"")}>
<div className={"row align-middle"}>
<div className="col-md-2 order-1 order-md-1 text-center border-right align-middle text-nowrap overflow-hidden">{(p.title&&p.song)?<>{p.song.name}<br/></>:<></>}{((p.play.fine==0&&p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?<span className="badge pfc">PFC</span>:(p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?<span className="badge fc">FC</span>:<></>)} <Difficulty play={p.play} song={p.song}/> {Math.floor(p.play.score)} pts</div>
<div className="col-md-3 order-3 order-md-2 text-center border-right align-middle text-nowrap overflow-hidden">{GetDateDisplay()}</div>
<div className="col-md-7 order-2 order-md-3">
<div className="row">
<div className="col-12 order-1 order-md-1 col-md-5 text-center">
{p.play.cool+"/"+p.play.fine+"/"+p.play.safe+"/"+p.play.sad+"/"+p.play.worst}
</div>
<div className="col-6 order-3 order-md-2 col-md-2 text-left text-md-left">
{(p.play.mod!==null&&p.play.mod.length>0)?
<ModDisplay side={true} badge={CalculateBadge(p.play.difficulty)} diff={GetModifiedDiff(p.play.difficulty)}
hs={p.play.mod=="HS"?1:0} hd={p.play.mod=="HD"?1:0} sd={p.play.mod=="SD"?1:0}/>
:<></>
}
</div>
<div className="col-6 order-2 order-md-3 col-md-3 text-right text-md-left">
<b>{p.play.percent}%</b>
</div>
<div className="col-6 order-2 order-md-3 col-md-2 text-right text-md-left">
{(p.play.src)?<IMAGE_CAMERA/>:<></>}
</div>
</div>
</div>
</div>
</div>
</div>
<div className={"d-block d-small d-md-none "+((p.play.src)?"background-songs-click":"")} onClick={(p.play.src)?()=>{p.setModalSrc(p.play)
p.setModalVisible(true)}:null}>
<div className={((p.play.fine==0&&p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?"pfchighlight":(p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?"fchighlight":"")}>{(p.title&&p.song)?<>{p.song.name}<br/></>:<></>}
{<div className="row"><div className="offset-4 col-4 text-center">{((p.play.fine==0&&p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?<span className="badge pfc">PFC</span>:(p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?<span className="badge fc">FC</span>:<></>)}<Difficulty play={p.play} song={p.song}/></div></div>}
<div className="row">
<div className="offset-2 col-4 text-center">
{Math.floor(p.play.score)} pts
<br/>
{p.play.cool+"/"+p.play.fine+"/"+p.play.safe+"/"+p.play.sad+"/"+p.play.worst}
</div>
<div className="col-4 text-center">
<b>{p.play.percent}%</b> {(p.play.mod!==null&&p.play.mod.length>0)?<ModDisplay side={true} badge={CalculateBadge(p.play.difficulty)} diff={GetModifiedDiff(p.play.difficulty)}
hs={p.play.mod=="HS"?1:0} hd={p.play.mod=="HD"?1:0} sd={p.play.mod=="SD"?1:0}/>:<></>}
<span className="pl-2"/>
{(p.play.src)?<IMAGE_CAMERA/>:<></>}
<br/>
{GetDateDisplay(true)}
</div>
</div>
</div>
</div>
</>
);
} else {
return (
<>
<div className={"row align-middle "+((p.play.fine==0&&p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?"pfchighlight":(p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?"fchighlight":"")+((p.play.src)?" background-songs-click":"")} onClick={(p.play.src)?()=>{p.setModalSrc(p.play)
p.setModalVisible(true)}:null}>
{(p.index!==undefined)?<div className=" col-md-1 text-center border-right align-middle text-nowrap overflow-hidden"><span className="d-none d-md-block">{p.index+1}</span>{((p.play.fine==0&&p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?<span className="badge pfc">PFC</span>:(p.play.safe==0&&p.play.sad==0&&p.play.worst==0)?<span className="badge fc">FC</span>:<></>)}</div>:<></>}
<div className="col-md-3 text-center border-right align-middle text-nowrap overflow-hidden"><SongName song={p.song}/><span className="tinytime">{GetDateDiff()}</span></div>
<div className="col-md-2 text-center border-right align-middle text-nowrap overflow-hidden">{Math.floor(p.play.score)} pts<br/><Difficulty play={p.play} song={p.song}/></div>
<div className="col-md-6">
<div className="row">
<div className="order-1 order-md-1 col-md-4 numbers text-center">
<div className="row justify-content-center">
<div className="col-4 col-md-5">
<img src={RATING_cool.src} className="pr-2" height="16"/>
</div>
<div className="col-4 col-md-7">
{p.play.cool}
</div>
</div>
</div>
<div className="order-3 order-md-2 col-md-4 numbers text-center">
<div className="row justify-content-center">
<div className="col-4 col-md-5">
<img src={RATING_safe.src} className="pr-2" height="16"/>
</div>
<div className="col-4 col-md-7">
{p.play.safe}
</div>
</div></div>
<div className="order-5 order-md-3 col-md-4 numbers text-center">
<div className="row justify-content-center">
<div className="col-4 col-md-5">
<img src={RATING_worst.src} className="pr-2" height="16"/>
</div>
<div className="col-4 col-md-7">
{p.play.worst}
</div>
</div></div>
<div className="order-2 order-md-4 order-sm-2 col-md-4 numbers text-center">
<div className="row justify-content-center">
<div className="col-4 col-md-5">
<img src={RATING_fine.src} className="pr-2" height="16"/>
</div>
<div className="col-4 col-md-7">
{p.play.fine}
</div>
</div></div>
<div className="order-4 order-md-5 col-md-4 numbers text-center">
<div className="row justify-content-center">
<div className="col-4 col-md-5">
<img src={RATING_sad.src} className="pr-2" height="16"/>
</div>
<div className="col-4 col-md-7">
{p.play.sad}
</div>
</div></div>
<div className="order-6 order-md-6 col-md-4 numbers text-center"><b>{p.play.percent}% {(p.play.src)?<span className="pl-4"><IMAGE_CAMERA onClick={()=>{p.setModalSrc(p.play)
p.setModalVisible(true)}}/></span>:<></>}</b></div>
</div>
</div>
</div>
</>
);
}
}
function LoadMore(p) {
var [offset,setOffset] = useState(p.params.limit)
var [params,setParams] = useState(p.params)
var [loading,setLoading] = useState(false)
var [visible,setVisible] = useState(false)
var [update,setUpdate] = useState(false)
useEffect(()=>{
axios.get(p.url+constructParams(params))
.then((data)=>{
if (data.data.length>0) {
setVisible(true)
}
})
},[update])
function constructParams(params) {
var st = Object.keys(params).reduce((str,key)=>{
if (str==="") {
return str+="?"+key+"="+params[key]
} else {
return str+="&"+key+"="+params[key]
}
},"")
return st
}
if (!visible){
return (<></>)
}
else
if (p.listItem) {
return (
<li className="list-group-item list-group-item-action homelink" onClick={()=>{
setLoading(true)
axios.get(p.url+constructParams(params))
.then((data)=>{
if (data.data.length>0) {
var newVals = [...p.value]
data.data.forEach((val)=>{
newVals.push(val)
})
p.setValue(newVals)
//console.log(newVals)
var obj = {...params}
obj.offset+=offset
setParams(obj)
setLoading(false)
if (data.data.length<p.params.limit) {
setVisible(false)
}
} else {
setVisible(false)
setLoading(false)
}
})
}
}>
<div className="row text-center">
<div className="col-12">
{(!loading)?<h6 className="link"><i>- Load More -</i></h6>:<div className="spinner-grow text-primary" role="status"><span className="sr-only">Loading...</span></div>
}
</div>
</div>
</li>
)
} else
return (
<div className="row text-center homelink" onClick={()=>{
setLoading(true)
axios.get(p.url+constructParams(params))
.then((data)=>{
if (!data.data) {
setVisible(false)
} else
if (data.data.length>0) {
var newVals = [...p.value]
data.data.forEach((val)=>{
newVals.push(val)
})
p.setValue(newVals)
//console.log(newVals)
var obj = {...params}
obj.offset+=offset
setParams(obj)
setLoading(false)
if (data.data.length<p.params.limit) {
setVisible(false)
}
} else {
setVisible(false)
setLoading(false)
}
})
}
}>
<div className="col-12">
{(!loading)?<h6 className="link"><i>- Load More -</i></h6>:<div className="spinner-grow text-primary" role="status"><span className="sr-only">Loading...</span></div>
}
</div>
</div>
)
}
function BestPlaysPanel(p) {
var [bestPlays,setBestPlays] = useState([])
var [update,setUpdate] = useState(false)
useEffect(()=>{
axios.get("http://www.projectdivar.com/bestplays/"+p.username+"?fails=false&limit=5&offset=0")
.then((data)=>{setBestPlays(data.data);})
},[update])
var content=<div className="col-md-12 mt-3 mb-3">
<ul className="list-group list-group-flush border border-danger rounded-lg">
{bestPlays.map((play,i)=>{return <li key={play.id} className={"list-group-item list-group-item-action "+(i%2==0?"background-list-1":"background-list-2")}>
<Play setModalSrc={p.setModalSrc} setModalVisible={p.setModalVisible} index={i} play={play} song={p.songs[play.songid]}/>
</li>})}
<LoadMore listItem={true} url={"http://www.projectdivar.com/bestplays/"+p.username} params={{fails:false,limit:15,offset:5}} value={bestPlays} setValue={setBestPlays}/>
</ul>
</div>
return (
<>
<div className="row ml-3 mr-3">
{content}
</div>
</>
);
}
function ModDisplay(p) {
const[tooltip,setTooltip] = useState("")
const[visibility,setVisibility] = useState(false)
return (
<span className={"border border-"+p.badge+" rounded "+p.diff+"-background"} style={{fontSize:"18px"}}>
{(p.hs>0)?<span style={{color:"#b33"}} onMouseOver={()=>{setTooltip("High Speed - "+p.diff.toUpperCase());setVisibility(true)}} onMouseOut={()=>{setVisibility(false)}}></span>:<></>}
{(p.hd>0)?<span onMouseOver={()=>{setTooltip("Hidden - "+p.diff.toUpperCase());setVisibility(true)}} onMouseOut={()=>{setVisibility(false)}} style={{color:"#968a0e"}}></span>:<></>}
{(p.sd>0)?<span onMouseOver={()=>{setTooltip("Sudden - "+p.diff.toUpperCase());setVisibility(true)}} onMouseOut={()=>{setVisibility(false)}} style={{color:"#49b"}}></span>:<></>}
{(visibility)?<span style={{position:"absolute"}} className={((p.side)?"display-tooltipside":"display-tooltip")+" alert alert-dark "+p.diff+"-background"}>{tooltip}</span>:<></>}
</span>
)
}
function PlayDetail(p) {
const[tooltip,setTooltip] = useState("")
const[visibility,setVisibility] = useState(false)
const[style,setStyle] = useState("")
return (
<>
<td>
{(p.song.report.rank>0)?p.song.report.rank:<i>Not Played</i>}
</td>
<td>
{(p.song.report.rank>0)?<>{p.song.report.score}</>:""}
</td>
<td>
{(p.song.report.rank>0)?<>{p.song.report.percent}%</>:""}
</td>
<td>
{p.song.report.ecount>0?<span className="badge badge-primary" onMouseOver={()=>{setTooltip(<>{p.song.report.eclearcount+" / "+p.song.report.ecount+" ("+(Math.floor((p.song.report.eclearcount/p.song.report.ecount)*100))+"% pass rate)"}{(p.song.report.efccount>0)?<><br/>{"★FC'd "+p.song.report.efccount+" time"+(p.song.report.efccount!=1?"s":"")}</>:<></>}{(p.song.report.epfccount>0)?<><br/>{"✪Perfected "+p.song.report.epfccount+" time"+(p.song.report.epfccount!=1?"s":"")}</>:<></>}</>);setStyle("easy");setVisibility(true)}} onMouseOut={()=>{setVisibility(false)}}>{p.song.report.epfccount>0?"":p.song.report.efccount>0?"":""}{p.song.report.ecount}</span>:<></>}
{p.song.report.ncount>0?<span className="badge badge-info" onMouseOver={()=>{setTooltip(<>{p.song.report.nclearcount+" / "+p.song.report.ncount+" ("+(Math.floor((p.song.report.nclearcount/p.song.report.ncount)*100))+"% pass rate)"}{(p.song.report.nfccount>0)?<><br/>{"★FC'd "+p.song.report.nfccount+" time"+(p.song.report.nfccount!=1?"s":"")}</>:<></>}{(p.song.report.npfccount>0)?<><br/>{"✪Perfected "+p.song.report.npfccount+" time"+(p.song.report.npfccount!=1?"s":"")}</>:<></>}</>);setStyle("normal");setVisibility(true)}} onMouseOut={()=>{setVisibility(false)}}>{p.song.report.npfccount>0?"":p.song.report.nfccount>0?"":""}{p.song.report.ncount}</span>:<></>}
{p.song.report.hcount>0?<span className="badge badge-success" onMouseOver={()=>{setTooltip(<>{p.song.report.hclearcount+" / "+p.song.report.hcount+" ("+(Math.floor((p.song.report.hclearcount/p.song.report.hcount)*100))+"% pass rate)"}{(p.song.report.hfccount>0)?<><br/>{"★FC'd "+p.song.report.hfccount+" time"+(p.song.report.hfccount!=1?"s":"")}</>:<></>}{(p.song.report.hpfccount>0)?<><br/>{"✪Perfected "+p.song.report.hpfccount+" time"+(p.song.report.hpfccount!=1?"s":"")}</>:<></>}</>);setStyle("hard");setVisibility(true)}} onMouseOut={()=>{setVisibility(false)}}>{p.song.report.hpfccount>0?"":p.song.report.hfccount>0?"":""}{p.song.report.hcount}</span>:<></>}
{p.song.report.excount>0?<span className="badge badge-warning" onMouseOver={()=>{setTooltip(<>{p.song.report.exclearcount+" / "+p.song.report.excount+" ("+(Math.floor((p.song.report.exclearcount/p.song.report.excount)*100))+"% pass rate)"}{(p.song.report.exfccount>0)?<><br/>{"★FC'd "+p.song.report.exfccount+" time"+(p.song.report.exfccount!=1?"s":"")}</>:<></>}{(p.song.report.expfccount>0)?<><br/>{"✪Perfected "+p.song.report.expfccount+" time"+(p.song.report.expfccount!=1?"s":"")}</>:<></>}</>);setStyle("ex");setVisibility(true)}} onMouseOut={()=>{setVisibility(false)}}>{p.song.report.expfccount>0?"":p.song.report.exfccount>0?"":""}{p.song.report.excount}</span>:<></>}
{p.song.report.exexcount>0?<span className="badge badge-danger" onMouseOver={()=>{setTooltip(<>{p.song.report.exexclearcount+" / "+p.song.report.exexcount+" ("+(Math.floor((p.song.report.exexclearcount/p.song.report.exexcount)*100))+"% pass rate)"}{(p.song.report.exexfccount>0)?<><br/>{"★FC'd "+p.song.report.exexfccount+" time"+(p.song.report.exexfccount!=1?"s":"")}</>:<></>}{(p.song.report.exexpfccount>0)?<><br/>{"✪Perfected "+p.song.report.exexpfccount+" time"+(p.song.report.exexpfccount!=1?"s":"")}</>:<></>}</>);setStyle("exex");setVisibility(true)}} onMouseOut={()=>{setVisibility(false)}}>{p.song.report.exexpfccount>0?"":p.song.report.exexfccount>0?"":""}{p.song.report.exexcount}</span>:<></>}
{(visibility)?<span style={{position:"absolute"}} className={"display-tooltip alert alert-dark "+style+"-background"}>{tooltip}</span>:<></>}
</td>
<td>
{(p.song.report.ehscount>0||p.song.report.ehdcount>0||p.song.report.esdcount>0)?
<ModDisplay badge="primary" diff="easy"
hs={p.song.report.ehscount} hd={p.song.report.ehdcount} sd={p.song.report.esdcount}/>
:<></>
}
{(p.song.report.nhscount>0||p.song.report.nhdcount>0||p.song.report.nsdcount>0)?
<ModDisplay badge="info" diff="normal"
hs={p.song.report.nhscount} hd={p.song.report.nhdcount} sd={p.song.report.nsdcount}/>
:<></>
}
{(p.song.report.hhscount>0||p.song.report.hhdcount>0||p.song.report.hsdcount>0)?
<ModDisplay badge="success" diff="hard"
hs={p.song.report.hhscount} hd={p.song.report.hhdcount} sd={p.song.report.hsdcount}/>
:<></>
}
{(p.song.report.exhscount>0||p.song.report.exhdcount>0||p.song.report.exsdcount>0)?
<ModDisplay badge="warning" diff="ex"
hs={p.song.report.exhscount} hd={p.song.report.exhdcount} sd={p.song.report.exsdcount}/>
:<></>
}
{(p.song.report.exexhscount>0||p.song.report.exexhdcount>0||p.song.report.exexsdcount>0)?
<ModDisplay badge="danger" diff="exex"
hs={p.song.report.exexhscount} hd={p.song.report.exexhdcount} sd={p.song.report.exexsdcount}/>
:<></>
}
</td>
</>
);
}
function PlayData(p) {
var [data,setData] = useState([])
var [update,setUpdate] = useState(false)
useEffect(()=>{
axios.get("http://projectdivar.com/plays/"+p.username+"/"+p.song.id)
.then((data)=>{setData(data.data);})
},[update])
return (
<>
<div className="text-center background-songs below">
<h5>Individual Plays for {p.song.name} from {p.username}</h5>
<div className="border rounded">
{data.map((play,i)=><Play setModalSrc={p.setModalSrc} setModalVisible={p.setModalVisible} key={i} play={play} mini={true} song={p.song}/>)}
<LoadMore url={"http://www.projectdivar.com/plays/"+p.username+"/"+p.song.id} params={{limit:15,offset:5}} value={data} setValue={setData}/>
</div>
</div>
</>
)
}
var cumulativeOffset = function(element) {
var top = 0, left = 0;
do {
top += element.offsetTop || 0;
left += element.offsetLeft || 0;
element = element.offsetParent;
} while(element);
return {
top: top,
left: left
};
};
function HoverSongName(p) {
let match = useRouteMatch({
path: "/user/"+p.username+"/"+p.to,
exact: true
});
var [name,setName] = useState(p.song.name)
var [expand,setExpand] = useState(<></>)
var [toggle,setToggle] = useState(match)
let history = useHistory();
useEffect(()=>{
if ((p.song.report.ecount+p.song.report.ncount+p.song.report.hcount+p.song.report.excount+p.song.report.exexcount>0)) {
if (toggle) {
setExpand(<tr className="fadein">
<td colSpan="6"><PlayData setModalSrc={p.setModalSrc} setModalVisible={p.setModalVisible} song={p.song} username={p.username}/></td>
</tr>)
window.scroll(0,cumulativeOffset(document.getElementById("songRow_"+p.song.name)).top-document.getElementById("songRow_"+p.song.name).getBoundingClientRect().height);
} else {
setExpand(<></>)
}
}
},[toggle])
return (
<>
<tr id={"songRow_"+p.song.name} key={p.song.id} className="lighthover cursor" onClick={(e)=>{
if ((p.song.report.ecount+p.song.report.ncount+p.song.report.hcount+p.song.report.excount+p.song.report.exexcount>0)) {
if (!toggle) {
setToggle(true)
history.push("/user/"+p.username+"/"+p.to)
} else {
setToggle(false)
}
}
//console.log(e.target.getBoundingClientRect()+"/"+window.pageYOffset)
}
}>
<td className="overflow-hidden">
{(p.song.report.ecount+p.song.report.ncount+p.song.report.hcount+p.song.report.excount+p.song.report.exexcount>0)?((toggle)?<></>:<>⯈</>):<></>} {name} <span className="tinytext">{(p.song.romanized_name.length>0)?<>{(p.song.romanized_name!==p.song.name)?<>{p.song.romanized_name}</>:<></>}</>:<>{(p.song.english_name!==p.song.name)?<>{p.song.english_name}</>:<></>}</>}</span>
</td>
<PlayDetail song={p.song}/>
</tr>
{expand}
</>
)
}
function CompletionPanel(p) {
const [report,setReport] = useState([])
const [song,setSong] = useState("")
const [filter,setFilter] = useState({})
const [style,setStyle] = useState(true)
const [update,setUpdate] = useState(false)
useEffect(()=>{
axios.get("http://projectdivar.com/completionreport/"+p.username)
.then((data)=>{setReport(data.data)})
.catch((err)=>{console.log(err.message)})
},[update])
return (
<>
<SongSearch songs={p.songs} song={song} setSong={setSong} setStyle={setStyle} filteredSongs={filter} setFilteredSongs={setFilter}/>
<table className="table table-sm">
<thead>
<tr id="headerbar">
<th scope="col" className={(style)?"scrollingHeader":""}>
Song Name
</th>
<th className={(style)?"scrollingHeader":""}>
Ranking
</th>
<th className={(style)?"scrollingHeader":""}>
Score
</th>
<th className={(style)?"scrollingHeader":""}>
%
</th>
<th className={(style)?"scrollingHeader":""}>
Play Count
</th>
<th className={(style)?"scrollingHeader":""}>
Mods
</th>
</tr>
</thead>
<tbody>
{report.filter((report)=>Object.keys(filter).length==0||report.id in filter).map((song,i)=>{return <HoverSongName setModalSrc={p.setModalSrc} setModalVisible={p.setModalVisible} to={song.name} song={song} key={song.id} username={p.username}/>
})}
</tbody>
<tfoot>
<tr><td colSpan="8" id="footer" className={(style)?"scrollingFooter":""}>
<span className="badge badge-primary">Easy</span> <span className="badge badge-info">Normal</span> <span className="badge badge-success">Hard</span> <span className="badge badge-warning">Extreme</span> <span className="badge badge-danger">Extra Extreme</span> <span className="badge badge-light"> = FC</span> <span className="badge badge-light"> = Perfect FCs</span>
</td></tr>
</tfoot>
</table>
</>
);
}
function Panel() {
return (
<>
[Placeholder Panel]
</>
);
}
const CalculateAccuracy=(cool,fine,safe,sad,worst)=>{
var noteCount = cool+fine+safe+sad+worst;
var sum = cool+(fine*0.5)+(safe*0.1)+(sad*0.05);
return Math.round((sum/noteCount)*10000)/100+"%";
}
function ClearBadge(p) {
var [display,setDisplay] = useState(<></>)
/*<span className="badge badge-primary">{easy}/{diffs.E}
{(fcdata&&fcdata.E>0)?<><br/>{fcdata.E}</>:<></>}
{(pfcdata&&pfcdata.E>0)?<><br/>{pfcdata.E}</>:<></>}</span>*/
function toggle(state) {
if (state) {
setDisplay(<>{((p.fcdata&&p.fcdata[p.diff]>0)?<><br/> {p.fcdata[p.diff]}</>:<></>)}
{((p.pfcdata&&p.pfcdata[p.diff]>0)?<><br/> {p.pfcdata[p.diff]}</>:<></>)}</>)
} else {
setDisplay(<></>)
}
}
useEffect(()=>{
toggle(p.mouseOver)
},[p.mouseOver])
return(
<>
<span className={"badge badge-"+CalculateBadge(p.diff)} onTouchStart={()=>{toggle(true)}}>{p.count}/{p.diffs[p.diff]}{display}</span>
</>
)
}
function Profile(p){
let { username } = useParams();
let match = useRouteMatch();
var [updateProfile,setProfile] = useState(false);
var [playcount,setPlayCount] = useState(0);
var [fccount,setFCCount] = useState(0);
var [cleared,setClear] = useState("");
var [accuracy,setAccuracy] = useState("-%");
var [rating,setRating] = useState(0);
var [lastPlayed,setLastPlayed] = useState(new Date());
var [update,setUpdate] = useState(false);
var [diffs,setDiffs] = useState({});
var [user,setUserData] = useState({});
var [render,setRender] = useState(false);
var [modalsrc,setModalSrc] = useState({})
var [modalVisible,setModalVisible] = useState(false);
var [mouseOver,setMouseOver] = useState(false);
function CalculateClear(easy,normal,hard,ex,exex,fcdata,pfcdata) {
return <>
<ClearBadge mouseOver={mouseOver} diff="E" count={easy} diffs={diffs} fcdata={fcdata} pfcdata={pfcdata}/>
<ClearBadge mouseOver={mouseOver} diff="N" count={normal} diffs={diffs} fcdata={fcdata} pfcdata={pfcdata}/>
<ClearBadge mouseOver={mouseOver} diff="H" count={hard} diffs={diffs} fcdata={fcdata} pfcdata={pfcdata}/>
<ClearBadge mouseOver={mouseOver} diff="EX" count={ex} diffs={diffs} fcdata={fcdata} pfcdata={pfcdata}/>
<ClearBadge mouseOver={mouseOver} diff="EXEX" count={exex} diffs={diffs} fcdata={fcdata} pfcdata={pfcdata}/>
</>
}
useEffect(()=>{
axios.get("http://projectdivar.com:4501/userdata/"+username)
.then((data)=>{setUserData(data.data);setPlayCount(data.data.playcount);setFCCount(data.data.fccount);setRating(data.data.rating);setLastPlayed(data.data.last_played);setAccuracy(CalculateAccuracy(data.data.cool,data.data.fine,data.data.safe,data.data.sad,data.data.worst))});
axios.get("http://projectdivar.com:4501/songdiffs")
.then((data)=>{setDiffs(data.data)})
},[update])
useEffect(()=>{
if (user!={}) {
setClear(CalculateClear(user.eclear,user.nclear,user.hclear,user.exclear,user.exexclear,user.fcdata,user.pfcdata))
}
},[diffs,user,mouseOver])
useEffect(()=>{
setRender(user!==undefined&&playcount!==undefined&&fccount!==undefined&&rating!==undefined&&lastPlayed!==undefined&&accuracy!==undefined&&diffs!==undefined&&cleared!==undefined)
},[user,playcount,fccount,rating,lastPlayed,accuracy,diffs,cleared])
return (
<>
<ImageDisplayer username={username} songs={p.songs} play={modalsrc} modalVisible={modalVisible} setModalVisible={setModalVisible}></ImageDisplayer>
<h2>{username+"'s Profile"}</h2>
{(render)?<>
<StatisticsPanel name="Statistics" setMouseOver={setMouseOver} username={username} playcount={playcount} fccount={fccount} cleared={cleared} accuracy={accuracy}/>
<HitCountsPanel name="Hit Counts" username={username} user={user}/>
<BestPlaysPanel name="Best Plays" setModalVisible={setModalVisible} setModalSrc={setModalSrc} username={username} songs={p.songs}/>
<CompletionPanel name="Progress" setModalVisible={setModalVisible} setModalSrc={setModalSrc} username={username} songs={p.songs}/>
<Panel name="Activity" username={username}/>
</>
:<></>
}
</>
);
}
function Rankings(){
let { sort,sortOrder } = useParams();
let match = useRouteMatch();
var [users,setUsers] = useState([]);
var [updateUsers,setUpdateUsers] = useState(false);
var [isLoading,setIsLoading] = useState(true);
useEffect(()=>{
axios.get("http://projectdivar.com:4501/users/"+sort+"/"+sortOrder+"?limit=100&offset=0")
.then((data)=>{setUsers(data.data)
setIsLoading(false);})
//.then(()=>{console.log(users)})
},[updateUsers])
return (
<>
<table>
<thead>
<tr>
<th className="header"><Sort setIsLoading={setIsLoading} updateUsers={updateUsers} setUpdateUsers={setUpdateUsers} label="Username" order="username"/></th>
<th className="header"><Sort setIsLoading={setIsLoading} updateUsers={updateUsers} setUpdateUsers={setUpdateUsers} label="Last Played" order="last_played"/></th>
<th className="header"><Sort setIsLoading={setIsLoading} updateUsers={updateUsers} updateUsers={updateUsers} setUpdateUsers={setUpdateUsers} setUpdateUsers={setUpdateUsers} label="Rating" order="rating"/></th>
<th className="header"><Sort setIsLoading={setIsLoading} updateUsers={updateUsers} setUpdateUsers={setUpdateUsers} label="Play Count" order="playcount"/></th>
<th className="header"><Sort setIsLoading={setIsLoading} updateUsers={updateUsers} setUpdateUsers={setUpdateUsers} label="FC Count" order="fccount"/></th>
</tr>
</thead>
{users.map((user,i)=>
<tbody key={i}>
<tr>
<td className={(isLoading)?"loading":""}><Link to={"/user/"+user.username}>{user.username}</Link></td>
<td className={(isLoading)?"loading":""} className={(isLoading)?"loading":""} className={(isLoading)?"loading":""}>{user.last_played}</td>
<td className={(isLoading)?"loading":""} className={(isLoading)?"loading":""}>{user.rating}</td>
<td className={(isLoading)?"loading":""}>{user.playcount}</td>
<td className={(isLoading)?"loading":""}>{user.fccount}</td>
</tr>
</tbody>)}
</table>
</>
);
}
function ImageUpload(p) {
var [file,setFile] = useState(null);
var [fileProcess,setFileProcess] = useState(0);
var [error,setError] = useState(null);
var [success,setSuccess] = useState(null);
var [fileProgress,setFileProgress] = useState(0);
var prepFile = (e)=>{
setFile(e.currentTarget.files[0])
setError(null);
}
var uploadFile = (e)=>{
setError(null);
if (!file) {setError("No file selected!");return;}
if (file.type!=="application/x-zip-compressed" &&
file.type!=="image/jpeg" && file.type!=="image/png") {
setError("File type is invalid! Please provide a .zip/.jpg/.png file!")
setFileProcess(0)
return;
}
const data = new FormData()
data.append('file', file)
data.append("username","GOD");
data.append("authentication_token","GOD");
if (!data.has("username") || !data.has("authentication_token")) {setError("Authentication failed!");return;}
if (file.size>15*1024*1024) {
setError("File size is too large! Max is 15MB! Consider splitting your plays into chunks (Recommended 50 files per zip).");return;
}
//console.log(file)
setFileProcess(1);
axios.post("http://projectdivar.com/upload", data, {
onUploadProgress: function(progressEvent) {
//console.log(progressEvent)
setFileProgress(Math.round((progressEvent.loaded * 100) / progressEvent.total))
}})
.then(res => {
setSuccess(res.data);
setFileProgress(100)
setFileProcess(0)
})
.catch((err)=>{setError(err.message);setFileProgress(0);setFileProcess(0)})
}
switch (fileProcess) {
default:{
return (
<form method="post" action="#" id="#">
<div className="files form-group color">
<h3>Submit your play</h3>
<i>Plays can be a single image or a bunch of images in a zip file!</i>
<hr/>
{(success!=null)?<h4 className="success">{success}</h4>:<></>}
<div style={{position:"relative",top:"0px"}}>
<input type="file" name="file" className="form-control" onChange={(e)=>{prepFile(e)}} disabled={fileProcess===1}/>
<div className="uploadicon"/>
<div className="dragText">or drag it here</div>
</div>
{(error!==null)?<div className="error">{error}</div>:<></>}
<button type="button" className="btn btn-primary btn-block" onClick={(e)=>{uploadFile(e)}} disabled={fileProcess===1}>
{fileProcess===1?<>Uploading...<span className="spinner-border"/>
<div className="progress" style={{position:"relative"}}>
<div className={"progress-bar"} style={{width:fileProgress+"%"}} role="progressbar" aria-valuemin="0" aria-valuemax="100"></div>
<div style={{position:"relative"}}>{fileProgress+"%"}</div>
</div>
</>:<>Upload</>}</button>
</div>
</form>);
}
}
}
function SongSearch(p) {
//Requires: p.songs / p.song / p.setSong / p.filteredSongs / p.setFilteredSongs
const [song,setSong] = useState("")
const [focused,setFocused] = useState(false)
useEffect(()=>{
if (p.setStyle) {
if (focused) {
p.setStyle(false)
} else {
p.setStyle(true)
}
}
},[focused])
return (
<>
<input className="form-control form-control-lg" value={song} placeholder={"🔍 Search by Song,Artist,Vocaloid"} onKeyDown={(e)=>{if (e.key==="Enter") {setFocused(false);e.target.blur()}}} onFocus={()=>{setFocused(true)}} onChange={(e)=>{
if (p.setFilteredSongs){p.setFilteredSongs({})}
setSong(e.target.value)
}
} onBlur={()=>{
setTimeout(()=>{setFocused(false)},250)
}
}/>
{(focused)?
<div className="overflow-auto rounded-lg" style={{background:"#eef",position:"absolute",width:"95%",height:"240px"}}>{
Object.keys(p.songs).filter((key)=>
{
var s = p.songs[key]
return s.name.toLowerCase().includes(song.toLowerCase())||s.romanized_name.toLowerCase().includes(song.toLowerCase())||s.english_name.toLowerCase().includes(song.toLowerCase())||s.artist.toLowerCase().includes(song.toLowerCase())||s.vocaloid.toLowerCase().includes(song.toLowerCase())
}).map((key)=>{
if (p.setFilteredSongs&&p.filteredSongs) {
var obj = p.filteredSongs;
obj[key]=true
//console.log(obj)
p.setFilteredSongs(obj)
}
return <div key={key} className="pb-1 homelink highest" onClick={()=>{setSong(p.songs[key].name);p.setSong(p.songs[key].name);setFocused(false);if(p.setFilteredSongs&&p.filteredSongs){var obj={};obj[key]=true;p.setFilteredSongs(obj)}}}>
<div className="d-flex flex-row">
<div className="p-2">
<img className="centered" src={p.songs[key].album_art.replace("album_art","album_art/small")}/>
</div>
<div className="p-8">
<h4>{p.songs[key].name}</h4>{(p.songs[key].romanized_name)?p.songs[key].romanized_name:p.songs[key].english_name}
</div>
</div>
</div>})}</div>:<></>}
More stuff goes here.
</>
)
}
function SimpleUpload(p){
const [song,setSong] = useState("")
const [percentage,setPercentage] = useState("")
return (
<>
<SongSearch song={song} setSong={setSong} songs={p.songs}/>
{(song.length>0?<>
<div className="input-group">
<div className="input-group-prepend">
<label htmlFor="validationCustomUsername">
<span className="input-group-text" id= "inputGroupPrepend">Song %</span>
</label>
<input type="text" className="form-control" id="validationCustomUsername" value={percentage} placeholder="101.46%" aria-describedby="inputGroupPrepend"
onChange={(e)=>{
if (!e.target.value.includes("%")) {
e.target.value+="%"
e.target.selectionStart=e.target.selectionEnd=e.target.value.length-1
}
setPercentage(e.target.value)}}
required/>
<small className="text-muted">
Input the % you got on the results screen.
</small>
</div>
</div>
</>:<></>)}
</>
)
}
function SendMail() {
//process.env.REACT_APP_FRONTEND_AUTH
return (
<>
</>
)
}
function Submit(p) {
return (
<div className="row">
<div className="col-12 col-md-8">
<Switch>
<Route path="/submitplay/simple">
<SimpleUpload songs={p.songs}/>
</Route>
<Route path="/submitplay/detail">
Detailed
</Route>
<Route path="/submitplay/switch">
Switch
</Route>
<Route path="/submitplay/image">
<ImageUpload/>
</Route>
<Route path="/submitplay">
<h2>Select a submission method</h2>
<div className="card">
<Link to="/submitplay/simple" className="nostyle">
<div className="card-body">
<h5 className="card-title">Manual Submit</h5>
<p className="card-text">Submit your plays by entering the clear % of a song</p>
<p className="card-text"><small className="text-muted">The simplest way to submit plays, type in a %, tweak the other values quickly, then submit your play! Optionally include a screenshot.</small></p>
</div>
</Link>
</div>
<br/>
<div className="card">
<Link to="/submitplay/image" className="nostyle">
<div className="card-body">
<h5 className="card-title">Image Upload</h5>
<p className="card-text">Upload images from your Nintendo Switch for automatic processing/scoring!</p>
<p className="card-text"><small className="text-muted">Put up to 50 images in a zip file to mass-upload your screenshotted plays to your profile. You will need to extract them from your microSD card from your Nintendo Switch.</small></p>
</div>
</Link>
</div>
<br/>
<div className="card">
<Link to="/submitplay/switch" className="nostyle">
<div className="card-body">
<h5 className="card-title">Nintendo Switch/Twitter Upload</h5>
<p className="card-text">Setup your account for uploading through Twitter using your Nintendo Switch!</p>
<p className="card-text"><small className="text-muted">You can select up to 4 images to post to Twitter at one time.</small></p>
</div>
</Link>
</div>
</Route>
</Switch>
</div>
</div>
)
}
function RecentPlays(p) {
const [update,setUpdate] = useState(false)
const [recentPlayData,setRecentPlayData] = useState([])
useEffect(()=>{
const interval = setInterval(()=>{
axios.get("http://projectdivar.com/recentplays/sigonasr2")
.then((data)=>{
setRecentPlayData(data.data);
})
.catch((err)=>{})
},5000);
return ()=>{clearInterval(interval)}
},[update])
return (
<>
{recentPlayData.map((play,i)=><Play index={i} play={play} song={p.songs[play.songid]} title={true} mini={true}/>)}
</>
)
}
function LoginInfo(p) {
const [username,setUsername] = useState(undefined)
const [authToken,setAuthToken] = useState(undefined)
const [loggedIn,setLoggedIn] = useState(false)
//Load our storage data if exists.
useEffect(()=>{
try {
setUsername(localStorage.getItem("username"))
setAuthToken(localStorage.getItem("authToken"))
}catch{
console.log("Not logged in!");
}
},[p.update])
useEffect(()=>{
if (username!==undefined&&authToken!==undefined) {
axios.post("http://projectdivar.com/authenticate/login",{username:username,authCode:authToken})
.then((data)=>{
setLoggedIn(true);
p.setUsername(username);
})
.catch((err)=>{
setLoggedIn(false);
})
}
},[username,authToken])
return (
<>
{loggedIn?<>
Welcome, <b>{username}</b>!<br/>
<Link to="/auth">App Auth Code</Link><br/>
</>:<>
<Link to="/login">Login</Link><br/>
<Link to="/register">Register</Link>
</>}
</>
)
}
function Login(p) {
const [username,setUsername] = useState("")
const [authCode,setAuthCode] = useState("")
const [authCodeVisible,setAuthCodeVisible] = useState(false)
const [error,setError] = useState(false)
const [disabled,setDisabled] = useState(false)
let history = useHistory();
if (p.isLoggedIn) {
history.push("/")
}
return (
<>
<Form>
{error&&<h3 style={{color:"red"}}>{error}</h3>}
{authCodeVisible&&<><h3>We have sent you an email containing your login code!</h3>
<br/>
Please submit it to finish the login process.
</>}
<Form.Group controlId="formUsername">
<Form.Label>Username</Form.Label>
<Form.Control disabled={authCodeVisible} isInvalid={username.length<1} onChange={(e)=>{setUsername(e.currentTarget.value)}} placeholder="MikuMiku" value={username} />
<Form.Text className="text-muted">
We will send an email to the registered email of this account.
</Form.Text>
</Form.Group>
{authCodeVisible&&<>
<div className="row">
<div className="col-4">
<Form.Group controlId="formCode">
<Form.Label>Authentication Code</Form.Label>
<Form.Control isInvalid={authCode.length!=5} onChange={(e)=>{setAuthCode(e.currentTarget.value)}} placeholder="XXXXX" value={authCode} />
<Form.Text className="text-muted">
Please enter the code you received in your email here. Then submit again.
</Form.Text>
</Form.Group>
</div>
</div></>
}
<Button disabled={disabled} variant="primary" type="submit" onClick={(e)=>{e.preventDefault()
if (username.length>=1) {
setDisabled(true)
setError(false)
if (authCode.length===5) {
axios.post("http://projectdivar.com/authenticate/login",{username:username,authCode:authCode})
.then((data)=>{
localStorage.setItem("username",username)
localStorage.setItem("authToken",authCode)
p.setLoginPanelUpdate(true)
history.push("/")
})
.catch((err)=>{
if (err) {
setError("Invalid Authentication Code!")
setDisabled(false)
}
})
} else {
axios.post("http://projectdivar.com/sendemail/login",{username:username})
.then((data)=>{
setAuthCodeVisible(true)
setDisabled(false)
})
.catch((err)=>{
if (err) {
setError("Invalid credentials provided!")
setDisabled(false)
}
})
}
}
}}>
{authCodeVisible?"Submit Code":"Login"}
</Button>
</Form>
</>
)
}
function Register(p) {
const [username,setUsername] = useState("")
const [email,setEmail] = useState("")
const [authCode,setAuthCode] = useState("")
const [authCodeVisible,setAuthCodeVisible] = useState(false)
const [error,setError] = useState(false)
const [disabled,setDisabled] = useState(false)
let history = useHistory();
if (p.isLoggedIn) {
history.push("/")
}
return (
<>
<Form>
{error&&<h3 style={{color:"red"}}>{error}</h3>}
{authCodeVisible&&<><h3>We have sent you an email containing your registration code!</h3>
<br/>
Please submit it to finish the registration process.
</>}
<Form.Group controlId="formUsername">
<Form.Label>Username</Form.Label>
<Form.Control disabled={authCodeVisible} isInvalid={username.length<1} onChange={(e)=>{setUsername(e.currentTarget.value)}} placeholder="MikuMiku" value={username} />
</Form.Group>
<Form.Group controlId="formEmail">
<Form.Label>Email Address</Form.Label>
<Form.Control disabled={authCodeVisible} type="email" disabled={authCodeVisible} isInvalid={email.length<1} onChange={(e)=>{setEmail(e.currentTarget.value)}} placeholder="MikuMiku@39.net" value={email} />
<Form.Text className="text-muted">
Please provide a valid email address! We use your email account as your "password", so it is a requirement for this site.
</Form.Text>
</Form.Group>
{authCodeVisible&&<>
<div className="row">
<div className="col-4">
<Form.Group controlId="formAuthCode">
<Form.Label>Authentication Code</Form.Label>
<Form.Control isInvalid={authCode.length!=5} onChange={(e)=>{setAuthCode(e.currentTarget.value)}} placeholder="XXXXX" value={authCode} />
<Form.Text className="text-muted">
Please enter the code you received in your email here. Then submit again.
</Form.Text>
</Form.Group>
</div>
</div></>
}
<Button disabled={disabled} variant="primary" type="submit" onClick={(e)=>{e.preventDefault()
if (username.length>=1&&email.length>=1) {
setDisabled(true)
setError(false)
if (authCode.length===5) {
axios.post("http://projectdivar.com/authenticate/login",{username:username,authCode:authCode})
.then((data)=>{
localStorage.setItem("username",username)
localStorage.setItem("authToken",authCode)
p.setLoginPanelUpdate(true)
return axios.patch("http://projectdivar.com/updateRegisteredState",{username:username,authCode:authCode})
})
.then((data)=>{
//console.log(data)
history.push("/")
})
.catch((err)=>{
if (err) {
setError("Invalid Authentication Code!")
setDisabled(false)
}
})
} else {
axios.post("http://projectdivar.com/sendemail/register",{username:username,email:email})
.then((data)=>{
setAuthCodeVisible(true)
setDisabled(false)
})
.catch((err)=>{
if (err) {
setError("Username or Email already in use!")
setDisabled(false)
}
})
}
}
}}>
{authCodeVisible?"Submit Code":"Register"}
</Button>
</Form>
</>
)
}
function UserAuth(p) {
const[showAuthCode,setShowAuthCode] = useState(false)
const[authToken,setAuthToken] = useState("")
let history = useHistory();
if (!p.isLoggedIn) {
history.push("/")
}
return(<>
Your <b>App Authentication Code</b> is used for verifying your identity when using apps such as <b>DivaBot</b>. By clicking the <b>{"<Reveal Code>"}</b> button, you understand that you should not share this code or show it to anyone!
<br/><br/>
{showAuthCode?
<input readOnly value={authToken}></input>
:<button onClick={()=>{
axios.post("http://projectdivar.com/authenticate/authToken",{username:localStorage.getItem("username"),
authCode:localStorage.getItem("authToken")})
.then((data)=>{
setAuthToken(data.data.authentication_token)
setShowAuthCode(true)
})
.catch((err)=>{
setAuthToken(err.message)
})
}
}>
{"<Click to reveal App Authentication Code>"}
</button>
}
</>)
}
function ReleaseList(p) {
return(
<>
<ul className="list-group">
{p.releases.map((release,i)=>
<li key={i} className="list-group-item">
<b>{release[0]}</b> - <a href={release[1]}>{release[1].replace("http://projectdivar.com/files/releases/","")}</a> <i>(Released {release[2]})</i>
</li>
)}
</ul>
</>
)
}
function DivaBot() {
const releases=[
["01B","http://projectdivar.com/files/releases/DivaBot01B.zip","13 Sep 2020"],
["01A","http://projectdivar.com/files/releases/DivaBot01A.zip","13 Sep 2020"],
["01","http://projectdivar.com/files/releases/DivaBot01.zip","13 Sep 2020"]]
return (
<>
<b>DivaBot</b> was created by <b>sigonasr2</b> in order to allow Project Diva streamers to personalize their stream setups with their personal scores and achievements into their game.
<br/><br/>
The app works by monitoring your game's capture area as you are streaming in order to identify what song you are playing, and what scores you achieve. It is used with this website to make score
submitting and tracking easier.
<br/>
The app currently supports <b>Megamix</b>. Other games will be supported in the future.
<hr/>
<h3>Setup Instructions</h3>
{<iframe width="100%" height="480" src="https://www.youtube.com/embed/IAPpbp5EFto" frameBorder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>}
<hr/>
<h3>Downloads</h3>
<ReleaseList releases={releases}/>
</>
)
}
function Website() {
const [songs,setSongs] = useState([])
const [update,setUpdate] = useState(false)
const [tooltip,setTooltip] = useState("")
const [loginPanelUpdate,setLoginPanelUpdate] = useState(false)
const [username,setUsername] = useState(undefined)
useEffect(()=>{
axios.get("http://www.projectdivar.com/songs")
.then((data)=>{
setSongs(data.data)
})
},[update])
return (
<div className="row">
<div className="col-md-2 pt-3 pb-3 overflow-hidden text-center">
<h3 className="d-none d-md-block">Menu</h3>
<LoginInfo setUsername={setUsername} update={loginPanelUpdate}/>
<br/><br/>
<Link to="/rankings/rating/desc">Rankings</Link><br/>
<Link to="/divabot">DivaBot</Link><br/>
</div>
<div className="col-md-10 pt-3 pb-3">
<Switch>
<Route path="/rankings/:sort/:sortOrder">
<Rankings/>
</Route>
<Route path="/user/:username">
{(songs)?
<Profile songs={songs}/>:<></>
}
</Route>
<Route path="/submitplay">
<Submit songs={songs}/>
</Route>
<Route path="/divabot">
<h1 className="title">DivaBot</h1>
<DivaBot/>
</Route>
<Route path="/auth">
<h1 className="title">App Authentication Token</h1>
<UserAuth username={username} isLoggedIn={username!==undefined}/>
</Route>
<Route path="/recentplays">
<h1 className="title">Project DivaR</h1>
<RecentPlays songs={songs}/>
</Route>
<Route path="/login">
<h1 className="title">Login to Project DivaR</h1>
<Login isLoggedIn={username!==undefined} setLoginPanelUpdate={setLoginPanelUpdate}/>
</Route>
<Route path="/register">
<h1 className="title">Register New Account</h1>
<Register isLoggedIn={username!==undefined} setLoginPanelUpdate={setLoginPanelUpdate}/>
</Route>
<Route path="/">
<h1 className="title">Project DivaR</h1>
Under construction!
</Route>
</Switch>
</div>
</div>
);
}
/*window.onmousemove = function(e) {
var obj = document.getElementById("display-tooltip")
if (obj!=null) {
//var offset = obj.parentElement.getBoundingClientRect();
var tipDist = 15;
obj.style.top = (e.clientY + tipDist) + 'px';
obj.style.left = (e.clientX + tipDist) + 'px';
}
}*/
function App() {
return (
<Router>
<div className="container-fluid content">
<div className="row">
<div className="topbar col-md-12 pt-1 overflow-hidden border rounded text-center">
<div>
<Link to="/">
<Logo/>
</Link>
</div>
</div>
</div>
<Website/>
</div>
</Router>
)
}
export default App;