Skip to content

Commit

Permalink
Merge pull request #274 from csfloat/272-visualize-an-items-float-in-…
Browse files Browse the repository at this point in the history
…a-float-bar

Visualize Item Floats in a Floatbar (Market + Inventory)
  • Loading branch information
GODrums authored Nov 26, 2024
2 parents 8519b08 + fe2746e commit e18a074
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/lib/components/inventory/selected_item_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {Observe} from '../../utils/observers';
import {FetchStallResponse} from '../../bridge/handlers/fetch_stall';
import {gStallFetcher} from '../../services/stall_fetcher';
import {Contract} from '../../types/float_market';
import '../../ui/floatbar';

/**
* Why do we bind to iteminfo0 AND iteminfo1?
Expand Down Expand Up @@ -101,6 +102,7 @@ export class SelectedItemInfo extends FloatElement {
const containerChildren: TemplateResult[] = [];

if (isSkin(this.asset.description) && this.itemInfo) {
containerChildren.push(this.renderFloatBar());
containerChildren.push(
html`<div>Float: ${this.itemInfo.floatvalue.toFixed(14)} ${renderClickableRank(this.itemInfo)}</div>`
);
Expand Down Expand Up @@ -130,6 +132,17 @@ export class SelectedItemInfo extends FloatElement {
return html` <div class="container">${containerChildren}</div> `;
}

renderFloatBar(): TemplateResult<1> {
if (!this.itemInfo || !this.itemInfo.floatvalue) {
return html``;
}

return html`
<float-bar float=${this.itemInfo.floatvalue} minFloat=${this.itemInfo.min} maxFloat=${this.itemInfo.max}>
</float-bar>
`;
}

renderFloatMarketListing(): TemplateResult<1> {
if (!this.stallListing) {
return html``;
Expand Down
19 changes: 17 additions & 2 deletions src/lib/components/market/item_row_wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {css, html, nothing} from 'lit';
import {css, html, nothing, TemplateResult} from 'lit';

import {state} from 'lit/decorators.js';
import {CustomElement, InjectAppend, InjectionMode} from '../injectors';
Expand All @@ -13,6 +13,7 @@ import {gFilterService} from '../../services/filter';
import {AppId, ContextId, Currency} from '../../types/steam_constants';
import {defined} from '../../utils/checkers';
import {pickTextColour} from '../../utils/colours';
import '../../ui/floatbar';

@CustomElement()
@InjectAppend('#searchResultsRows .market_listing_row .market_listing_item_name_block', InjectionMode.CONTINUOUS)
Expand All @@ -22,6 +23,7 @@ export class ItemRowWrapper extends FloatElement {
css`
.float-row-wrapper {
margin-bottom: 5px;
max-width: max(50%, 400px);
}
`,
];
Expand Down Expand Up @@ -158,7 +160,9 @@ export class ItemRowWrapper extends FloatElement {

return html`
<div class="float-row-wrapper">
Float: ${this.itemInfo.floatvalue.toFixed(14)} ${renderClickableRank(this.itemInfo)}<br />
${this.renderFloatBar()}
<span> Float: ${this.itemInfo.floatvalue.toFixed(14)} ${renderClickableRank(this.itemInfo)} </span>
<br />
Paint Seed:
${formatSeed(this.itemInfo)}${fadePercentage !== undefined
? html`<br />
Expand All @@ -178,4 +182,15 @@ export class ItemRowWrapper extends FloatElement {
return html`<div>Loading...</div>`;
}
}

renderFloatBar(): TemplateResult<1> {
if (!this.itemInfo) {
return html``;
}

return html`
<float-bar float=${this.itemInfo.floatvalue} minFloat=${this.itemInfo.min} maxFloat=${this.itemInfo.max}>
</float-bar>
`;
}
}
91 changes: 91 additions & 0 deletions src/lib/ui/floatbar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {LitElement, html, css} from 'lit';
import {customElement, property} from 'lit/decorators.js';

@customElement('float-bar')
export class FloatBar extends LitElement {
@property({type: Number}) float!: number;
@property({type: Number}) minFloat = 0;
@property({type: Number}) maxFloat = 1;

static styles = css`
.market-float-bar-container {
position: relative;
width: 100%;
height: 8px;
margin: 5px 0;
}
.market-float-bar-marker {
position: absolute;
background-color: #d9d9d9;
width: 3px;
top: -3px;
height: 14px;
border-radius: 4px;
}
.market-float-bar {
display: inline-block;
vertical-align: top;
height: 100%;
opacity: 0.8;
}
.market-float-bar:first-of-type {
border-radius: 4px 0 0 4px;
}
.market-float-bar:last-of-type {
border-radius: 0 4px 4px 0;
}
`;

private readonly floatConditions = [
{min: 0, max: 7, color: 'green'},
{min: 7, max: 15, color: '#18a518'},
{min: 15, max: 38, color: '#9acd32'},
{min: 38, max: 45, color: '#cd5c5c'},
{min: 45, max: 100, color: '#f92424'},
];

get minFloatPercentage(): number {
return this.minFloat * 100;
}

get maxFloatPercentage(): number {
return this.maxFloat * 100;
}

render() {
const left = this.minFloatPercentage.toFixed(0);
const markerLeft = (((this.float - this.minFloat) * 100) / (this.maxFloat - this.minFloat)).toFixed(3);
const dynamicWidth = this.maxFloatPercentage - this.minFloatPercentage;

const getConditionWidth = (condMin: number, condMax: number) => {
return (
Math.max(
0,
(Math.min(condMax, this.maxFloatPercentage) - Math.max(condMin, this.minFloatPercentage)) * 100
) / dynamicWidth
);
};

return html`
<div class="market-float-bar-container" style="left: ${left}%; width: ${dynamicWidth.toFixed(2)}%;">
<div style="height: 100%; border-radius: 4px; overflow: hidden; font-size: 0;">
${this.floatConditions.map(
(cond) => html`
<div
class="market-float-bar"
style="width: ${getConditionWidth(
cond.min,
cond.max
)}%; background-color: ${cond.color};"
></div>
`
)}
</div>
<div class="market-float-bar-marker" style="left: calc(${markerLeft}% - 2px);"></div>
</div>
`;
}
}

0 comments on commit e18a074

Please sign in to comment.