Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Necro Release #18

Merged
merged 3 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions services/activities/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ func main() {
{"Bandos shield", "Bandos warshield"},
{"Scriptures", "Scripture"},
{"Erethdor's grimoire", "Erethdor's grimoire (token)"},
{"Dragonrider Lance", "Dragon Rider lance"},
{"Wand Of The Cwyir Elders", "Wand Of The Cywir Elders"},
}

rootPassword := os.Getenv("MYSQL_ROOT_PASSWORD")
Expand Down
40 changes: 31 additions & 9 deletions services/stats/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,15 @@ func generateSkillQuery(skill string, skillId int, playerId int) string {
}

func main() {
var dryRun = false
rootPassword := os.Getenv("MYSQL_ROOT_PASSWORD")

var officialApiUrl = "https://secure.runescape.com/m=hiscore/index_lite.ws?player="
var connectionString = "root:" + rootPassword + "@tcp(containers-us-west-150.railway.app:7266)/railway"

// will be overwritten with necro
var numSkills = 29

db, err := sql.Open("mysql", connectionString)
if err != nil {
panic(err.Error())
Expand All @@ -55,7 +61,12 @@ func main() {
defer db.Close()

// query the database for the players to update
results, err := db.Query("SELECT id, username FROM Player where isTracking = true")
var queryString = "SELECT id, username FROM Player where isTracking = true"
if dryRun {
queryString = "SELECT id, username FROM Player where isTracking = true and id = 1"
}

results, err := db.Query(queryString)
if err != nil {
panic(err.Error())
}
Expand Down Expand Up @@ -112,7 +123,14 @@ func main() {
// skill insert
var skillQuery strings.Builder
skillQuery.WriteString("insert into Skill values ")
for j := 0; j < 29; j++ {

// check if necro is in skill list
if len(splitResponse[29]) == 3 {
// add 1 to numSkills
numSkills = numSkills + 1
}

for j := 0; j < numSkills; j++ {
if splitResponse[j] != "" {
skillQuery.WriteString(generateSkillQuery(splitResponse[j], j, playerId))
if j != 28 {
Expand All @@ -123,15 +141,17 @@ func main() {
}
}

_, err = db.Exec(skillQuery.String())
if err != nil {
panic(err.Error())
if !dryRun {
_, err = db.Exec(skillQuery.String())
if err != nil {
panic(err.Error())
}
}

// minigame insert
var minigameQuery strings.Builder
minigameQuery.WriteString("insert into Minigame values ")
for j := 29; j < len(splitResponse); j++ {
for j := numSkills; j < len(splitResponse); j++ {
if splitResponse[j] != "" {
minigameQuery.WriteString(generateMinigameQuery(splitResponse[j], j, playerId))
if j != len(splitResponse)-2 {
Expand All @@ -142,9 +162,11 @@ func main() {
}
}

_, err = db.Exec(minigameQuery.String())
if err != nil {
panic(err.Error())
if !dryRun {
_, err = db.Exec(minigameQuery.String())
if err != nil {
panic(err.Error())
}
}

log := fmt.Sprintf("> created for: %s", players[i].Username)
Expand Down
21 changes: 18 additions & 3 deletions src/components/ActivityList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { skillNameArray, skillIcon } from "../utils/constants";
import type { StaticImageData } from "next/image";
import Avatar from "./Avatar";
import Coins from "../assets/images/coins.png";
import LoadingSpinner from "./LoadingSpinner";

const formatDate = (date: string): string => {
// date format: 21-Jan-2023 00:31
Expand Down Expand Up @@ -107,7 +108,7 @@ const formatActivity = (
<p className="text-md md:text-md mr-1 truncate font-semibold">
{activity.username.split("+").join(" ")}
</p>
<Avatar username={activity.username} width="w-12" />
<Avatar username={activity.username} width="max-w-12 max-h-12" />
</div>
)}
</div>
Expand All @@ -118,21 +119,35 @@ type ActivityListProps = {
activities: Activity[];
username?: string;
title?: string;
loading?: boolean;
};

const ActivityList = ({ activities, username, title }: ActivityListProps) => {
const ActivityList = ({
activities,
username,
title,
loading,
}: ActivityListProps) => {
const router = useRouter();
return (
<div className="z-0 flex h-full w-full flex-col rounded drop-shadow-dark">
<p className="bg-gray-300 py-4 text-center text-lg font-bold text-gray-800 dark:bg-zinc-900 dark:text-text-dark">
{title ?? "Activities"}
</p>
{activities.length > 0 ? (

{loading && (
<div className="flex h-full w-full flex-col items-center justify-center overflow-x-hidden overflow-y-hidden">
<LoadingSpinner size="h-24 w-24 my-[20vh] md:my-0" />
</div>
)}
{activities.length > 0 && !loading ? (
<div className="flex h-full w-full flex-col overflow-x-hidden overflow-y-scroll">
{activities.map((activity: Activity, i: number) =>
formatActivity(activity, i, !username, router)
)}
</div>
) : loading ? (
<div />
) : (
<p className="bg-gray-400 py-4 text-center text-lg font-bold dark:bg-zinc-800">
{`${username}'s RuneMetrics profile is set to private.`}
Expand Down
7 changes: 7 additions & 0 deletions src/components/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useState } from "react";
type props = {
username: string;
width?: string;
};

const Avatar = ({ username, width = "w-full" }: props) => {
const [imgKey, setImgKey] = useState(0);
const formattedUsername = username.split(" ").join("+");
const url = `https://secure.runescape.com/m=avatar-rs/${formattedUsername}/chat.png`;

Expand All @@ -13,11 +15,16 @@ const Avatar = ({ username, width = "w-full" }: props) => {
return (
<img
src={url}
key={imgKey}
alt="avatar"
className={width}
onError={({ currentTarget }) => {
currentTarget.onerror = null; // prevents looping
currentTarget.src = backupUrl;
if (imgKey === 0) {
currentTarget.src = url;
setImgKey(1);
}
}}
/>
);
Expand Down
93 changes: 93 additions & 0 deletions src/components/NecroList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { useRouter } from "next/router";
import type { TopRankedPlayer } from "../types/user-types";
import { skillIcon, skillNameArray } from "../utils/constants";
import Avatar from "./Avatar";
import { trpc } from "../utils/trpc";
import LoadingSpinner from "./LoadingSpinner";

const formatPlayer = (
player: TopRankedPlayer,
i: number,
skillId: number,
router?: ReturnType<typeof useRouter>
) => {
return (
<div
key={i}
className={`${
i % 2 === 0
? "bg-background-light dark:bg-background-dark"
: "bg-gray-200 dark:bg-zinc-800"
} flex w-full items-center justify-between p-3 text-gray-800 hover:brightness-110 dark:text-text-dark`}
>
<div className="flex w-6/12 flex-row items-center justify-start">
<div className="flex flex-col items-center pr-2 text-sm">{i + 1}</div>
<div
onClick={() => router?.push(`/rs3/${player.username}`)}
className="flex w-9/12 cursor-pointer flex-col items-center hover:underline xl:flex-row"
>
<Avatar username={player.username} width="max-w-12 max-h-12" />
<p className="text-md ml-2 truncate font-semibold">
{player.displayName}
</p>
</div>
</div>
<div className={`flex w-3/12 flex-row items-center justify-end`}>
<div>
<p className={`text-md truncate font-normal text-white`}>
{player.xp.toLocaleString()} xp
</p>
{player.level && (
<p className={`truncate text-sm font-normal text-white`}>
Level {player.level}
</p>
)}
</div>
<img
className={`mr-2 h-10 w-10 p-2`}
src={skillIcon(skillId).src}
alt="skill icon"
/>
</div>
</div>
);
};

type TopDxpListProps = {
skillId: number;
};

const NecroList = ({ skillId }: TopDxpListProps) => {
const router = useRouter();
const title = `Top ${skillNameArray[skillId]} Players`;

const { isFetching, data } = trpc.player.getTopNecroPlayers.useQuery(
undefined,
{
refetchOnMount: true,
}
);

const players = data?.find((d) => d.skillId === skillId)?.players ?? [];

return (
<div className="flex h-full w-full flex-col rounded drop-shadow-dark">
<p className="bg-gray-300 py-4 text-center text-lg font-bold text-gray-800 dark:bg-zinc-900 dark:text-text-dark">
{title}
</p>
{!isFetching && players.length > 0 ? (
<div className="flex h-full w-full flex-col overflow-x-hidden overflow-y-scroll">
{players.map((player: TopRankedPlayer, i: number) =>
formatPlayer(player, i, skillId, router)
)}
</div>
) : (
<div className="flex h-full w-full flex-col items-center justify-center overflow-x-hidden overflow-y-hidden">
<LoadingSpinner size="h-24 w-24 my-[20vh] md:my-0" />
</div>
)}
</div>
);
};

export default NecroList;
2 changes: 1 addition & 1 deletion src/components/TopDxpList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const formatPlayer = (
onClick={() => router?.push(`/rs3/${player.username}`)}
className="flex w-9/12 cursor-pointer flex-col items-center hover:underline xl:flex-row"
>
<Avatar username={player.username} width="w-12" />
<Avatar username={player.username} width="max-w-12 max-h-12" />
<p className="text-md ml-2 truncate font-semibold">
{player.displayName}
</p>
Expand Down
70 changes: 39 additions & 31 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import ActivityList from "../components/ActivityList";
import LoadingSpinner from "../components/LoadingSpinner";
import type { Activity, TopPlayer } from "../types/user-types";
import TopDxpList from "../components/TopDxpList";
import { isCurrentlyDxp } from "../utils/constants";
import NecroList from "../components/NecroList";
import {
isCurrentlyDxp,
necroReleased,
TotalSkillsRs3,
} from "../utils/constants";
const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_MEASUREMENT_ID;

const Home: NextPageWithLayout = () => {
Expand All @@ -29,9 +34,9 @@ const Home: NextPageWithLayout = () => {
const { isFetching: isXpFetching } = getGains.useQuery(undefined, {
refetchOnMount: true,
onSuccess: (data) => setXpData(data),
enabled: false,
});

const showActivities = activities && activities.length > 0;
const handleSearch = (e: any) => {
setLoading(true);
e.preventDefault();
Expand Down Expand Up @@ -64,41 +69,44 @@ const Home: NextPageWithLayout = () => {
`}
</Script>
<main className="border-box max-w-screen mx-auto flex h-full flex-col items-center justify-start bg-background-light p-4 py-20 dark:bg-background-dark md:max-h-[100vh] md:min-h-[90vh]">
<div className="flex h-full w-full flex-col items-center md:w-11/12 md:flex-row md:items-start">
<div className="order-2 mt-10 flex w-full items-center justify-center md:order-1 md:h-[60vh] md:w-4/12">
<div className="flex h-full w-full flex-col items-center gap-4 md:w-11/12 md:flex-row md:items-start">
<div className="order-2 mt-10 flex w-full items-center justify-center md:order-1 md:h-[80vh] md:w-4/12">
{isXpFetching && !xpData && (
<LoadingSpinner size="h-24 w-24 my-[20vh] md:my-0" />
)}
{xpData && <TopDxpList players={xpData} />}
<NecroList skillId={0} />
</div>
<div className="order-1 flex h-full flex-col items-center justify-center px-[3rem] md:order-2 md:mt-[30vh] md:w-4/12">
<h1 className="text-5xl font-extrabold leading-normal text-gray-700 dark:text-white md:text-[4rem]">
Woodcut
</h1>
<form
onSubmit={handleSearch}
className="flex h-20 flex-col items-center md:flex"
>
<input
type="text"
className="mb-2 mr-2 block h-full rounded-lg border border-zinc-300 bg-zinc-50 p-2 text-center text-lg text-zinc-900 focus:border-zinc-500 focus:ring-zinc-500 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white dark:placeholder-zinc-400 dark:focus:border-zinc-500 dark:focus:ring-zinc-500"
placeholder="Search for a player"
required
onChange={(e) => setSearch(e.target.value)}
/>
<button
onClick={handleSearch}
className="flex h-full w-36 items-center justify-center rounded bg-forest-500 py-2 font-bold text-white hover:brightness-110"
>
{loading ? <LoadingSpinner size="h-8 w-8" /> : "Search"}
</button>
</form>
<div className="order-1 mt-10 flex w-full items-center justify-center md:order-1 md:h-[80vh] md:w-4/12">
<NecroList skillId={TotalSkillsRs3 - 1} />
</div>
<div className="order-3 mt-10 flex w-full items-center justify-center md:h-[60vh] md:w-4/12">
{isFetching && !activities && (
<LoadingSpinner size="hidden md:block h-24 w-24" />
)}
{showActivities && <ActivityList activities={activities} />}
{false && (
<div className="order-1 flex h-full flex-col items-center justify-center px-[3rem] md:order-2 md:mt-[30vh] md:w-4/12">
<h1 className="text-5xl font-extrabold leading-normal text-gray-700 dark:text-white md:text-[4rem]">
Woodcut
</h1>
<form
onSubmit={handleSearch}
className="flex h-20 flex-col items-center md:flex"
>
<input
type="text"
className="mb-2 mr-2 block h-full rounded-lg border border-zinc-300 bg-zinc-50 p-2 text-center text-lg text-zinc-900 focus:border-zinc-500 focus:ring-zinc-500 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white dark:placeholder-zinc-400 dark:focus:border-zinc-500 dark:focus:ring-zinc-500"
placeholder="Search for a player"
required
onChange={(e) => setSearch(e.target.value)}
/>
<button
onClick={handleSearch}
className="flex h-full w-36 items-center justify-center rounded bg-forest-500 py-2 font-bold text-white hover:brightness-110"
>
{loading ? <LoadingSpinner size="h-8 w-8" /> : "Search"}
</button>
</form>
</div>
)}
<div className="order-3 mt-10 flex w-full items-center justify-center md:h-[80vh] md:w-4/12">
<ActivityList activities={activities ?? []} loading={isFetching} />
</div>
</div>
</main>
Expand Down
1 change: 1 addition & 0 deletions src/pages/rs3/[username].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const Rs3: NextPageWithLayout = () => {
refetchIntervalInBackground: false,
onError: (error) => setError(error.data?.code ?? ""),
onSuccess: () => setError(""),
onSettled: () => setLoadingMessage(""),
}
);

Expand Down
Loading