std::shared_ptr<BackgroundAnimation> CreateBGAforVSRG(VSRG::Song &input, uint8_t DifficultyIndex, Interruptible *context) { VSRG::Difficulty* Diff = input.GetDifficulty(DifficultyIndex); if (Diff) { if (Diff->Data && Diff->Data->BMPEvents) return std::make_shared<BMSBackground>(context, Diff, &input); if (Diff->Data && Diff->Data->TimingInfo && Diff->Data->TimingInfo->GetType() == VSRG::TI_OSUMANIA) return std::make_shared<osuBackgroundAnimation>(context, Diff->Data->osbSprites.get(), &input); return std::make_shared<StaticBackground>(context, GetSongBackground(input)); } return nullptr; }
GString GetSVGText(int diffIndex, double intervalduration = 1, double peakMargin = 1.2) { std::stringstream out; vector<int> dataPoints = GetDataPoints(diffIndex, intervalduration); auto peak_it = std::max_element(dataPoints.begin(), dataPoints.end()); float peakf = *peak_it; double peak = *peak_it * peakMargin; out << "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n"; auto ptIdx = 0; float ImageHeight = CfgValNPS("GraphHeight", 300); float GraphYOffset = CfgValNPS("GraphYOffs", 50); float GraphXOffset = CfgValNPS("GraphXOffs", 100); float IntervalWidth = 10; float GraphWidth = dataPoints.size() * IntervalWidth; float RealGraphWidth = CfgValNPS("Width", 1000); float XRatio = RealGraphWidth / GraphWidth; Vec2 BL(GraphXOffset, GraphYOffset + ImageHeight); Vec2 BR(RealGraphWidth, 0); Vec2 TL(GraphXOffset, GraphYOffset); BR += BL; GString DiffAuth = Song->GetDifficulty(diffIndex)->Author; if (!DiffAuth.length()) DiffAuth = "an anonymous charter"; float avgNPS = Song->GetDifficulty(diffIndex)->TotalScoringObjects / Song->GetDifficulty(diffIndex)->Duration; out << Utility::Format("<text x=\"%d\" y=\"%d\" fill=\"black\">%s - %s (%s) by %s (Max NPS: %.2f/Avg NPS: %.2f)</text>\n", 20, 20, Song->SongName, Song->SongAuthor, Song->GetDifficulty(diffIndex)->Name, DiffAuth, peakf / intervalduration, avgNPS); out << Utility::Format("\t<line x1 = \"%d\" y1 = \"%d\" x2 = \"%d\" y2 = \"%d\" style = \"stroke:rgb(0,0,0);stroke-width:4\"/>\n", BL.x, BL.y, BR.x, BR.y); out << Utility::Format("\t<line x1 = \"%d\" y1 = \"%d\" x2 = \"%d\" y2 = \"%d\" style = \"stroke:rgb(0,0,0);stroke-width:4\"/>\n", TL.x, TL.y, BL.x, BL.y); auto ptAmt = 5; for (auto i = 1; i <= ptAmt; i++) { float X = (BL.x - GraphXOffset / 2); float Y = (BL.y - i * (ImageHeight / ptAmt / peakMargin)); float Value = (peakf * i / ptAmt / intervalduration); out << Utility::Format("\t<text x=\"%d\" y=\"%d\" fill=\"black\">%.2f</text>\n", X, Y, Value); out << Utility::Format("\t<line x1 = \"%d\" y1 = \"%d\" x2 = \"%d\" y2 = \"%d\" style = \"stroke:rgb(0,0,0);stroke-width:0.5\"/>\n", X, Y, GraphXOffset + RealGraphWidth, Y); } for (auto point : dataPoints) { double relativeFreq = point / peak; double relFreqNext; int x1, y1, x2, y2; if (ptIdx + 1 < dataPoints.size()) { relFreqNext = dataPoints[ptIdx + 1] / peak; } else relFreqNext = 0; x1 = IntervalWidth * ptIdx * XRatio + GraphXOffset; y1 = ImageHeight - ImageHeight * relativeFreq + GraphYOffset; x2 = IntervalWidth * (ptIdx + 1) * XRatio + GraphXOffset; y2 = ImageHeight - ImageHeight * relFreqNext + GraphYOffset; out << Utility::Format("\t<line x1 = \"%d\" y1 = \"%d\" x2 = \"%d\" y2 = \"%d\" style = \"stroke:rgb(255,0,0);stroke-width:2\"/>\n", x1, y1, x2, y2); ptIdx++; } out << "</svg>"; return out.str(); }