Skip to content

Commit

Permalink
refactor: use explicit lodash imports (#418)
Browse files Browse the repository at this point in the history
* refactor: reduce lodash dependence

* update lodash imports

* remove last chain

* remove filter and first
  • Loading branch information
vinceau authored Jan 25, 2024
1 parent f7b9271 commit 6913563
Show file tree
Hide file tree
Showing 17 changed files with 101 additions and 96 deletions.
19 changes: 10 additions & 9 deletions src/broadcast/broadcast_manager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Preconditions } from "@common/preconditions";
import { ConnectionEvent, ConnectionStatus, DolphinConnection, DolphinMessageType } from "@slippi/slippi-js";
import { EventEmitter } from "events";
import _ from "lodash";
import keyBy from "lodash/keyBy";
import last from "lodash/last";
import type { connection, Message } from "websocket";
import { client as WebSocketClient } from "websocket";

Expand Down Expand Up @@ -229,7 +230,7 @@ export class BroadcastManager extends EventEmitter {
switch (message.type) {
case "start-broadcast-resp": {
if (message.recoveryGameCursor !== undefined) {
const firstIncoming = _.first(this.incomingEvents);
const firstIncoming = this.incomingEvents[0];
let firstCursor: number | null | undefined;
if (firstIncoming) {
firstCursor = firstIncoming.cursor;
Expand All @@ -246,24 +247,24 @@ export class BroadcastManager extends EventEmitter {
const isNeededByServer = event.cursor > message.recoveryGameCursor;

// Make sure we aren't duplicating anything that is already in the incoming events array
const isNotIncoming = _.isNil(firstCursor) || event.cursor < firstCursor;
const isNotIncoming = firstCursor == null || event.cursor < firstCursor;

return isNeededByServer && isNotIncoming;
}
return false;
});

this.incomingEvents = _.concat(backedEventsToUse, this.incomingEvents);
this.incomingEvents = [...backedEventsToUse, ...this.incomingEvents];

const newFirstEvent = _.first(this.incomingEvents);
const newFirstEvent = this.incomingEvents[0];
if (!newFirstEvent) {
this.emit(BroadcastEvent.LOG, "Missing new first event");
return;
}
const newFirstCursor = newFirstEvent.cursor;

const firstBackupCursor = (_.first(this.backupEvents) || {}).cursor;
const lastBackupCursor = (_.last(this.backupEvents) || {}).cursor;
const firstBackupCursor = (this.backupEvents[0] || {}).cursor;
const lastBackupCursor = (last(this.backupEvents) || {}).cursor;

this.emit(
BroadcastEvent.LOG,
Expand All @@ -281,7 +282,7 @@ export class BroadcastManager extends EventEmitter {
// Grab broadcastId we were currently using if the broadcast still exists, would happen
// in the case of a reconnect
if (this.broadcastId) {
const broadcastsById = _.keyBy(broadcasts, "id");
const broadcastsById = keyBy(broadcasts, "id");
const prevBroadcast = broadcastsById[this.broadcastId];

if (prevBroadcast) {
Expand Down Expand Up @@ -397,7 +398,7 @@ export class BroadcastManager extends EventEmitter {
return;
}

while (!_.isEmpty(this.incomingEvents)) {
while (this.incomingEvents.length > 0) {
const event = this.incomingEvents.shift();
if (!event) {
this.emit(BroadcastEvent.LOG, "No incoming events");
Expand Down
1 change: 0 additions & 1 deletion src/broadcast/spectate_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Preconditions } from "@common/preconditions";
import { SlpFileWriter, SlpFileWriterEvent } from "@slippi/slippi-js";
import { EventEmitter } from "events";
import * as fs from "fs-extra";
import _ from "lodash";
import type { connection, Message } from "websocket";
import { client as WebSocketClient } from "websocket";

Expand Down
2 changes: 1 addition & 1 deletion src/dolphin/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { app } from "electron";
import electronLog from "electron-log";
import { EventEmitter } from "events";
import * as fs from "fs-extra";
import { debounce } from "lodash";
import debounce from "lodash/debounce";
import path from "path";
import { fileExists } from "utils/file_exists";

Expand Down
2 changes: 1 addition & 1 deletion src/dolphin/setup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { app, shell } from "electron";
import log from "electron-log";
import * as fs from "fs-extra";
import { isEqual } from "lodash";
import isEqual from "lodash/isEqual";
import path from "path";
import { fileExists } from "utils/file_exists";

Expand Down
2 changes: 1 addition & 1 deletion src/renderer/app/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Button from "@mui/material/Button";
import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import log from "electron-log";
import { debounce } from "lodash";
import debounce from "lodash/debounce";
import React, { useCallback, useMemo } from "react";

import { useDolphinActions } from "@/lib/dolphin/use_dolphin_actions";
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/dual_pane.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styled from "@emotion/styled";
import { debounce } from "lodash";
import debounce from "lodash/debounce";
import React from "react";

import { colors } from "@/styles/colors";
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/pages/replays/replay_browser/file_list.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DeleteIcon from "@mui/icons-material/Delete";
import FolderIcon from "@mui/icons-material/Folder";
import type { FileResult } from "@replays/types";
import { debounce } from "lodash";
import debounce from "lodash/debounce";
import React from "react";
import AutoSizer from "react-virtualized-auto-sizer";
import { FixedSizeList as List } from "react-window";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import TimerIcon from "@mui/icons-material/Timer";
import TrackChangesIcon from "@mui/icons-material/TrackChanges";
import type { FileResult } from "@replays/types";
import { frameToGameTimer, GameMode, stages as stageUtils } from "@slippi/slippi-js";
import { groupBy } from "lodash";
import groupBy from "lodash/groupBy";
import moment from "moment";
import React, { useCallback, useMemo } from "react";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import styled from "@emotion/styled";
import Typography from "@mui/material/Typography";
import type { FileResult } from "@replays/types";
import type { StatsType } from "@slippi/slippi-js";
import _ from "lodash";
import React from "react";

import { ErrorBoundary } from "@/components/error_boundary";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import Tooltip from "@mui/material/Tooltip";
import type { FileResult, PlayerInfo as PlayerInfoType } from "@replays/types";
import type { StadiumStatsType, StatsType } from "@slippi/slippi-js";
import { frameToGameTimer, GameMode, stages as stageUtils } from "@slippi/slippi-js";
import { get, groupBy } from "lodash";
import get from "lodash/get";
import groupBy from "lodash/groupBy";
import moment from "moment";
import React from "react";

Expand Down
19 changes: 11 additions & 8 deletions src/renderer/pages/replays/replay_file_stats/kill_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import Tooltip from "@mui/material/Tooltip";
import type { FileResult, PlayerInfo } from "@replays/types";
import type { StatsType, StockType } from "@slippi/slippi-js";
import { animations as animationUtils, Frames, moves as moveUtils } from "@slippi/slippi-js";
import _ from "lodash";
import get from "lodash/get";
import groupBy from "lodash/groupBy";
import keyBy from "lodash/keyBy";
import last from "lodash/last";

import { convertFrameCountToDurationString } from "@/lib/time";
import { getCharacterIcon } from "@/lib/utils";
Expand Down Expand Up @@ -97,13 +100,13 @@ export const KillTable = ({ file, stats, player, opp, onPlay }: KillTableProps)
const renderKilledBy = (stock: StockType) => {
// Here we are going to grab the opponent's punishes and see if one of them was
// responsible for ending this stock, if so show the kill move, otherwise assume SD
const punishes = _.get(stats, "conversions") || [];
const punishesByPlayer = _.groupBy(punishes, "playerIndex");
const punishes = get(stats, "conversions") || [];
const punishesByPlayer = groupBy(punishes, "playerIndex");
const playerPunishes = punishesByPlayer[opp.playerIndex] || [];

// Only get punishes that killed
const killingPunishes = _.filter(playerPunishes, "didKill");
const killingPunishesByEndFrame = _.keyBy(killingPunishes, "endFrame");
const killingPunishes = playerPunishes.filter((punish) => punish.didKill);
const killingPunishesByEndFrame = keyBy(killingPunishes, "endFrame");
const punishThatEndedStock =
stock.endFrame !== null && stock.endFrame !== undefined ? killingPunishesByEndFrame[stock.endFrame] : null;

Expand All @@ -112,7 +115,7 @@ export const KillTable = ({ file, stats, player, opp, onPlay }: KillTableProps)
return <span>Self Destruct</span>;
}

const lastMove = _.last(punishThatEndedStock.moves);
const lastMove = last(punishThatEndedStock.moves);
if (!lastMove) {
return <span>Grab Release</span>;
}
Expand Down Expand Up @@ -160,8 +163,8 @@ export const KillTable = ({ file, stats, player, opp, onPlay }: KillTableProps)
};

const renderStocksRows = () => {
const stocks = _.get(stats, "stocks") || [];
const stocksByOpponent = _.groupBy(stocks, "playerIndex");
const stocks = get(stats, "stocks") || [];
const stocksByOpponent = groupBy(stocks, "playerIndex");
const opponentStocks = stocksByOpponent[opp.playerIndex] || [];

return opponentStocks.map(generateStockRow);
Expand Down
44 changes: 21 additions & 23 deletions src/renderer/pages/replays/replay_file_stats/overall_table.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { FileResult } from "@replays/types";
import type { RatioType, StatsType } from "@slippi/slippi-js";
import _ from "lodash";
import get from "lodash/get";
import pick from "lodash/pick";
import toArray from "lodash/toArray";

import { getCharacterIcon } from "@/lib/utils";

Expand Down Expand Up @@ -55,8 +57,8 @@ export const OverallTable = ({ file, stats }: OverallTableProps) => {
) => {
const key = `standard-field-${header}`;

const arr = _.get(stats, arrPath) || [];
const itemsByPlayer = arr; // _.keyBy(arr, "playerIndex");
const arr = get(stats, arrPath) || [];
const itemsByPlayer = arr; // keyBy(arr, "playerIndex");

if (!arr || arr.length === 0) {
return (
Expand All @@ -66,15 +68,11 @@ export const OverallTable = ({ file, stats }: OverallTableProps) => {
</T.TableRow>
);
}
const player1Item = arrPathExtension ? _.get(itemsByPlayer[0], arrPathExtension) : itemsByPlayer[0] || {};
const player2Item = arrPathExtension ? _.get(itemsByPlayer[1], arrPathExtension) : itemsByPlayer[1] || {};
const player1Item = arrPathExtension ? get(itemsByPlayer[0], arrPathExtension) : itemsByPlayer[0] || {};
const player2Item = arrPathExtension ? get(itemsByPlayer[1], arrPathExtension) : itemsByPlayer[1] || {};
const generateValues = (item: any) => {
if (fieldPaths !== null) {
return _.chain(item)
.pick(fieldPaths)
.toArray()
.map((v) => (valueMapper ? valueMapper(v) : v))
.value();
return toArray(pick(item, fieldPaths)).map((v) => (valueMapper ? valueMapper(v) : v));
}

if (valueMapper) {
Expand Down Expand Up @@ -106,8 +104,8 @@ export const OverallTable = ({ file, stats }: OverallTableProps) => {
fieldPath: string,
ratioRenderer: (ratio: RatioType, oppRatio: RatioType) => JSX.Element,
) => {
const arr = _.get(stats, arrPath) || [];
const itemsByPlayer = arr; // _.keyBy(arr, "playerIndex");
const arr = get(stats, arrPath) || [];
const itemsByPlayer = arr; // keyBy(arr, "playerIndex");

const player1Item = itemsByPlayer[0] || {};
const player2Item = itemsByPlayer[1] || {};
Expand All @@ -116,8 +114,8 @@ export const OverallTable = ({ file, stats }: OverallTableProps) => {
const item = firstPlayer ? player1Item : player2Item;
const oppItem = firstPlayer ? player2Item : player1Item;

const ratio = _.get(item, fieldPath);
const oppRatio = _.get(oppItem, fieldPath);
const ratio = get(item, fieldPath);
const oppRatio = get(oppItem, fieldPath);

return ratioRenderer(ratio, oppRatio);
};
Expand All @@ -139,8 +137,8 @@ export const OverallTable = ({ file, stats }: OverallTableProps) => {
highlightCondition: (a: number, b: number) => boolean,
) => {
return renderRatioStatField(header, arrPath, fieldPath, (ratio: RatioType, oppRatio: RatioType) => {
const playerRatio = _.get(ratio, "ratio", null);
const oppRatioType = _.get(oppRatio, "ratio", null);
const playerRatio = get(ratio, "ratio", null);
const oppRatioType = get(oppRatio, "ratio", null);

if (playerRatio === null) {
return (
Expand All @@ -166,8 +164,8 @@ export const OverallTable = ({ file, stats }: OverallTableProps) => {
highlightCondition: (a: number, b: number) => boolean,
) => {
return renderRatioStatField(header, arrPath, fieldPath, (ratio, oppRatio) => {
const playerRatio = _.get(ratio, "ratio", null);
const oppRatioType = _.get(oppRatio, "ratio", null);
const playerRatio = get(ratio, "ratio", null);
const oppRatioType = get(oppRatio, "ratio", null);

if (playerRatio === null || oppRatioType === null) {
return (
Expand All @@ -179,8 +177,8 @@ export const OverallTable = ({ file, stats }: OverallTableProps) => {
const fixedPlayerRatio = playerRatio.toFixed(3);
const fixedOppRatio = oppRatioType.toFixed(3);

const playerCount = _.get(ratio, "count");
const playerTotal = _.get(ratio, "total");
const playerCount = get(ratio, "count");
const playerTotal = get(ratio, "total");

return (
<T.TableCell highlight={highlightCondition(parseFloat(fixedPlayerRatio), parseFloat(fixedOppRatio))}>
Expand Down Expand Up @@ -226,10 +224,10 @@ export const OverallTable = ({ file, stats }: OverallTableProps) => {
highlightCondition: (a: number, b: number) => boolean,
) => {
return renderRatioStatField(header, arrPath, fieldPath, (ratio: RatioType, oppRatio: RatioType) => {
const playerCount = _.get(ratio, "count") || 0;
const playerRatio = _.get(ratio, "ratio");
const playerCount = get(ratio, "count") || 0;
const playerRatio = get(ratio, "ratio");

const oppCount = _.get(oppRatio, "count") || 0;
const oppCount = get(oppRatio, "count") || 0;

let secondaryDisplay = null;
if (playerRatio !== null) {
Expand Down
25 changes: 14 additions & 11 deletions src/renderer/pages/replays/replay_file_stats/punish_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { css } from "@emotion/react";
import Tooltip from "@mui/material/Tooltip";
import type { FileResult, PlayerInfo } from "@replays/types";
import type { ConversionType, StatsType, StockType } from "@slippi/slippi-js";
import _ from "lodash";
import get from "lodash/get";
import groupBy from "lodash/groupBy";
import keyBy from "lodash/keyBy";
import range from "lodash/range";

import { convertFrameCountToDurationString } from "@/lib/time";
import { getCharacterIcon, toOrdinal } from "@/lib/utils";
Expand Down Expand Up @@ -99,7 +102,7 @@ export const PunishTable = ({ file, stats, player, opp, onPlay }: PunishTablePro
const totalStocks = player.startStocks;
const currentStocks = stock.count - 1;

const stockIcons = _.range(1, totalStocks != null ? totalStocks + 1 : 1).map((stockNum) => {
const stockIcons = range(1, totalStocks != null ? totalStocks + 1 : 1).map((stockNum) => {
return (
<T.GrayableImage
key={`stock-image-${stock.playerIndex}-${stockNum}`}
Expand All @@ -123,7 +126,7 @@ export const PunishTable = ({ file, stats, player, opp, onPlay }: PunishTablePro

const getPlayer = (playerIndex: number) => {
const players = file.game.players || [];
const playersByIndex = _.keyBy(players, "playerIndex");
const playersByIndex = keyBy(players, "playerIndex");
return playersByIndex[playerIndex];
};

Expand Down Expand Up @@ -177,21 +180,21 @@ export const PunishTable = ({ file, stats, player, opp, onPlay }: PunishTablePro
};

const renderPunishRows = () => {
const punishes = _.get(stats, "conversions") || [];
const punishesByPlayer = _.groupBy(punishes, "playerIndex");
const punishes = get(stats, "conversions") || [];
const punishesByPlayer = groupBy(punishes, "playerIndex");
const playerPunishes = punishesByPlayer[opp.playerIndex] || [];

const stocks = _.get(stats, "stocks") || [];
const stocksTakenFromPlayer = _.groupBy(stocks, "playerIndex");
const stocks = get(stats, "stocks") || [];
const stocksTakenFromPlayer = groupBy(stocks, "playerIndex");
const opponentStocks = stocksTakenFromPlayer[opp.playerIndex] || [];

const elements: JSX.Element[] = [];

const addStockRows = (punish?: ConversionType) => {
const shouldDisplayStockLoss = () => {
// Calculates whether we should display a stock loss row in this position
const currentStock = _.first(opponentStocks);
if (!currentStock || currentStock.endFrame === null || currentStock.endFrame === undefined) {
const currentStock = opponentStocks[0];
if (!currentStock || currentStock.endFrame == null) {
return false;
}

Expand All @@ -208,7 +211,7 @@ export const PunishTable = ({ file, stats, player, opp, onPlay }: PunishTablePro
// rendered one after another. but will initialize to true if we are considering
// the very first punish, this is the handle the case where someone SD's on first
// stock
let shouldAddEmptyState = punish === _.first(playerPunishes);
let shouldAddEmptyState = punish === playerPunishes[0];
while (shouldDisplayStockLoss()) {
const stock = opponentStocks.shift();

Expand All @@ -231,7 +234,7 @@ export const PunishTable = ({ file, stats, player, opp, onPlay }: PunishTablePro

// Special case handling when a player finishes their opponent without getting hit
// on their last stock. Still want to show an empty state
const stock = _.first(opponentStocks);
const stock = opponentStocks[0];
if (stock && addedStockRow && !punish) {
const emptyPunishes = generateEmptyRow(stock);
elements.push(emptyPunishes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import type { FileResult } from "@replays/types";
import { GameMode } from "@slippi/slippi-js";
import _ from "lodash";
import { useQuery } from "react-query";

import { BasicFooter } from "@/components/footer/footer";
Expand Down
Loading

0 comments on commit 6913563

Please sign in to comment.