Skip to content

Commit

Permalink
Merge pull request #18 from zeepk/necro
Browse files Browse the repository at this point in the history
Necro Release
  • Loading branch information
zeepk authored Aug 7, 2023
2 parents 20041d0 + c9385b8 commit dec09bd
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 44 deletions.
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

0 comments on commit dec09bd

Please sign in to comment.