So I'm trying to create a table map responsively with React, circles are generated by kanva for each seat added in JSON.
What happens is that I'm managing to separate the seats into columns, but I can't make these seats stay around the central circle (the table), could someone help me just how to make the circles stay around the central circle?
Here's the code i'm using to generate and align the seats with the table.
export const SEAT_SIZE = 10;
export const SEATS_DISTANCE = 15;
export const SUBSECTION_PADDING = 30;
export const SECTIONS_MARGIN = 10;
export const SECTION_TOP_PADDING = 40;
export const SECTION_TITLE_PADDING = 5;
export const X_TABLE = 45;
export const Y_TABLE = 36.8;
export const RADIUS_TABLE = SEAT_SIZE * 1.2;
This is the reference for creating tables and seats dynamically.
const Seat = props => {
const isBooked = props.data.status === "booked";
return (
<Circle
x={props.x}
y={props.y}
radius={SEAT_SIZE / 2}
fill={getColor(isBooked, props.isSelected)}
strokeWidth={1}
onMouseEnter={e => {
e.target._clearCache();
props.onHover(props.data.name, e.target.getAbsolutePosition());
const container = e.target.getStage().container();
if (isBooked) {
container.style.cursor = "not-allowed";
} else {
container.style.cursor = "pointer";
}
}}
onMouseLeave={e => {
props.onHover(null);
const container = e.target.getStage().container();
container.style.cursor = "";
}}
onClick={e => {
if (isBooked) {
return;
}
if (props.isSelected) {
props.onDeselect(props.data.name);
} else {
props.onSelect(props.data.name);
}
}}
onTap={e => {
if (isBooked) {
return;
}
if (props.isSelected) {
props.onDeselect(props.data.name);
} else {
props.onSelect(props.data.name);
}
}}
/>
);
};
The findX and findY functions are the functions I'm using to try to align the seats around the table, I'm doing everything related to that in them
function findX(rowIndex, seatIndex) {
let x = 25.8;
let isPair = seatIndex % 2 == 0 ? true : false;
if (!isPair) {
x += 40;
}
return x;
}
function findY(rowIndex, seatIndex) {
let y = seatIndex > 4 ? + 5 : 25;
y += 15 * (rowIndex + 1);
return y;
}
This code is what creates the seats dynamically, using the references
{Object.keys(data.map_qtd_fileiras).map((rowKey, rowIndex) => {
const row = data.map_qtd_fileiras[rowKey];
return (
<React.Fragment key={rowKey}>
{row.map((seat, seatIndex) => {
return (
<Group key={'group-' + seat.name}>
<Table
radius={SEAT_SIZE * 1.2}
key={'table-' + seat.name}
data={seat}
mb={8}
onHover={onHoverSeat}
onSelect={onSelectSeat}
onDeselect={onDeselectSeat}
isSelected={selectedSeatsIds.indexOf(seat.name) >= 0}
/>
<Seat
key={seat.name}
x={seatIndex > 4
? findY(rowIndex, seatIndex)
: findX(rowIndex, seatIndex)}
y={seatIndex > 4
? findX(rowIndex, seatIndex)
: findY(rowIndex, seatIndex)}
data={seat}
onHover={onHoverSeat}
onSelect={onSelectSeat}
onDeselect={onDeselectSeat}
isSelected={selectedSeatsIds.indexOf(seat.name) >= 0}
/>
</Group>
);
})}
And this is the reference JSON:
{
"seats": {
"sections": [
{
"event_id": "2",
"name": "\u00c1REA VIP",
"color": null,
"subsections": [
{
"id": "5",
"section_id": 1,
"name": "VIP 5",
"map_qtd_fileiras": {
"1": [
{
"name": "D1",
"status": "free"
},
{
"name": "D1",
"status": "free"
}
],
"2": [
{
"name": "D1",
"status": "free"
},
{
"name": "D1",
"status": "free"
}
],
"3": [
{
"name": "D1",
"status": "free"
},
{
"name": "D1",
"status": "free"
}
],
"4": [
{
"name": "D1",
"status": "free"
},
{
"name": "D1",
"status": "free"
}
]
}
}
]
}
]
}
}
And my return is exactly this:
Here
But I need a return similar to this:
Here
Related
Example JSON file:
[
{
"discordId": "9273927302020",
"characters": [
{
"name": "Rare_Character",
"value": 1
},
{
"name": "Ultra_Rare_Character",
"value": 1
}
]
}
]
Let's just say for example I ran this simple gacha and got 4 characters:
let i = 1
var picks = []
while(i <= 4){
const { pick } = gacha.simple(alpha)
picks.push(pick)
i++
}
Now, picks has an array like this:
[
{
"name": "Common_Character"
},
{
"name": "Ultra_Rare_Character"
},
{
"name": "Common_Character"
},
{
"name": "Rare_Character"
}
]
How do I increment the value in My Example JSON file based on the name from what I got in my gacha results picks while ignoring the Common_Character and only passing those Rare and Ultra_Rare ones?
I've tried filtering them like this:
var filter = picks.filter(t => t.name === 'Rare_Character' || t.name === 'Ultra_Rare_Character')
Now I don't know how to increase those values in my JSON file and what if in the gacha results I got two Rare_Characters or Ultra_Rare_Character
I'm using fs to read my JSON file but I just don't know the logic to increase values
const src = [
{
"discordId": "9273927302020",
"characters": [
{
"name": "Rare_Character",
"value": 1
},
{
"name": "Ultra_Rare_Character",
"value": 1
}
]
}
];
const gacha = [
{
"name": "Common_Character"
},
{
"name": "Ultra_Rare_Character"
},
{
"name": "Common_Character"
},
{
"name": "Rare_Character"
}
];
const updateValues = (src, gacha) => {
const gachaSums = gacha.reduce((collector, current) => {
collector[current.name] = (collector[current.name] | 0) + 1;
return collector;
}, {});
src.characters.forEach(srcChar => {
gachaSums[srcChar.name] = srcChar.value + (gachaSums[srcChar.name] | 0);
});
src.characters = Object.entries(gachaSums).map(([key, value]) =>
({ name: key, value: value })
);
return src;
}
console.log(updateValues(src[0], gacha));
Maybe this version could help
I get an input like this:
input 1:
{
"name": "Ben",
"description": "Ben",
"attributes": [
{
"type": "Background",
"value": "Default"
},
{
"type": "Hair-color",
"value": "Brown"
}
]
}
input 2
{
"name": "Ice",
"description": "Ice",
"attributes": [
{
"type": "Background",
"value": "Green"
},
{
"type": "Hair-color",
"value": "White"
}
]
}
input 3
{
"name": "Itay",
"description": "Itay",
"attributes": [
{
"type": "Background",
"value": "Default"
},
{
"type": "Hair-color",
"value": "Brown"
}
]
}
What I want to do is count the amount of each type of background and each type of hair-color appearing.
(These are sample examples and in reality there are more types and different values)
Let's say in these examples we have 2 objects that have a background as default then I want to have a count of that like so:
export interface TraitCount {
value: string,
count: number
}
export interface CountOfEachAttribute {
trait_type: string,
trait_count: traitCount[] | null,
total_variations: number
}
I want the most effective code because there are other aspects to the code, in addition it will run on 5-10k queries not just three, so needs
to run in good times too :D
(It's similar to my other question done with python but now I need it in js also)
Atm it's something like this:
(Apart of a much bigger code so keep that in mind)
setInitalCountOfAllAttribute( state, { payload }: PayloadAction<CountOfEachAttribute[] | null> ) {
if (payload === null) {
state.countOfAllAttribute = null;
} else {
state.countOfAllAttribute = payload;
}
},
setCountOfAllAttribute(state, { payload }: PayloadAction<Attribute>) {
if (state.countOfAllAttribute !== null) {
state.countOfAllAttribute.map(
(countOfEachAttribute: CountOfEachAttribute) => {
// Find the trait type
if (countOfEachAttribute.trait_type === payload.trait_type) {
// initiate the trait count array to store all the trait values and add first trait value
if (countOfEachAttribute.trait_count === null) {
const new_trait_count = { value: payload.value, count: 1 };
countOfEachAttribute.trait_count = [new_trait_count];
countOfEachAttribute.total_variations++;
}
// Trait array already existed.
else {
// Check if value already present or not
const checkValue = (obj: any) => obj.value === String(payload.value);
const isPresent = countOfEachAttribute.trait_count.some(checkValue)
const isPresent2 = countOfEachAttribute.trait_count.find((elem: any) => elem.value === String(payload.value))
// Value matched, increase its count by one
if (isPresent2) {
countOfEachAttribute.trait_count &&
countOfEachAttribute.trait_count.map((trait) => {
if (trait.value === payload.value) {
trait.count++;
}
});
}
// Value doesn't match, add a new entry and increase the count of variations by one
else {
const new_trait_count = { value: payload.value, count: 1 };
countOfEachAttribute.trait_count = [
...countOfEachAttribute.trait_count,
new_trait_count,
];
countOfEachAttribute.total_variations++;
}
}
}
}
);
}
},
You can merge all arrays and use Array.reduce.
const input1 = {
"name": "Ben",
"description": "Ben",
"attributes": [{
"type": "Background",
"value": "Default"
},
{
"type": "Hair-color",
"value": "Brown"
}
]
}
const input2 = {
"name": "Ice",
"description": "Ice",
"attributes": [{
"type": "Background",
"value": "Green"
},
{
"type": "Hair-color",
"value": "White"
}
]
}
const input3 = {
"name": "Itay",
"description": "Itay",
"attributes": [{
"type": "Background",
"value": "Default"
},
{
"type": "Hair-color",
"value": "Brown"
}
]
}
const mergedInput = [input1, input2, input3];
const result = mergedInput.reduce((acc, item) => {
item.attributes.forEach(attrItem => {
const existType = acc.find(e => e.trait_type == attrItem.type);
if (existType) {
var existAttr = existType.trait_count.find(e => e.value == attrItem.value);
if (existAttr) {
existAttr.count++;
} else {
existType.trait_count.push({
value: attrItem.value,
count: 1
});
existType.total_variations++;
}
} else {
acc.push({
trait_type: attrItem.type,
trait_count: [{
value: attrItem.value,
count: 1
}],
total_variations: 1
})
}
});
return acc;
}, []);
console.log(result);
I suggest instead of creating an array for trait_count to make it an object so you don't have to iterate over it whenever you are adding a new attribute. In the snippet below I'm using the value of the attribute as a sort of hash that allows the access to the given property without having to call the Array.prototype.find function
const input1 = {"name":"Ben","description":"Ben","attributes":[{"type":"Background","value":"Default"},{"type":"Hair-color","value":"Brown"}]};
const input2 = {"name":"Ice","description":"Ice","attributes":[{"type":"Background","value":"Green"},{"type":"Hair-color","value":"White"}]};
const input3 = {"name":"Itay","description":"Itay","attributes":[{"type":"Background","value":"Default"},{"type":"Hair-color","value":"Brown"}]};
function countAtributes(input, totalCounts={}) {
input.attributes.forEach((attribute) => {
if (!totalCounts[attribute.type])
totalCounts[attribute.type] = {trait_type: attribute.type, trait_count: {}, total_variations: 0};
if (!totalCounts[attribute.type].trait_count[attribute.value]) {
totalCounts[attribute.type].trait_count[attribute.value] = {value: attribute.value, count: 1};
totalCounts[attribute.type].total_variations+=1;
}
else totalCounts[attribute.type].trait_count[attribute.value].count +=1;
})
}
const totalCounts = {};
countAtributes(input1, totalCounts);
countAtributes(input2, totalCounts);
countAtributes(input3, totalCounts);
console.log(totalCounts);
It could be turned into the array afterwards with Object.values if necessary
I believe it is a much better approach to what you had before as you don't have to iterate over the tables of trait_counts. In theory it should significantly reduce the time taken. Iterating over the array and checking a condition each time is much slower than key lookup in Javascript object
I have a search input in my angular application that should compare the input data with different object properties
<div class="forms">
<div class="search-wrapper">
<input
class="search"
[ngClass]="{'searching': searching}"
type="text"
(input)="changeSearch($event.target.value)"
/>
<label class="">
<span>Rechercher</span>
</label>
</div>
</div>
the logic I use is as follows
public changeSearch(searchTerm: string) {
this.searching = !!searchTerm;
if (!this.searching) {
this.orders.forEach(order => {
order.show = true;
});
return;
}
const extendSearchIn = ['order_number', 'transaction.item.product.name'];
this.orders.forEach(order => {
order.show = true;
extendSearchIn.forEach(property => {
this.searchByProperty(order, property, searchTerm);
});
});
}
public searchByProperty(order, property, searchTerm) {
const prop = this.getSearchProperty(order, property);
if (prop === undefined) { return false; }
return (<String>prop.toLowerCase()).startsWith(searchTerm.toLowerCase());
}
public getSearchProperty(item: object, property: string) {
let itemCopy = Object.assign({}, item);
let result: any;
const props = property.split('.');
props.forEach(prop => {
if (itemCopy !== undefined) {
itemCopy = itemCopy[prop];
}
});
result = itemCopy !== undefined ? itemCopy : result;
return result;
}
and the structure of each object 'order' is like the following
{
"functional_id": "202006101058160012400000SD4AYAA1",
"transactions": [
{
"quantity": 2,
"price": 140,
"item": {
"name": "Carton",
"description": "+ 2 recharges",
"product": {
"name": "Coffret rouge"
}
},
"amount": 280
},
{
"quantity": 2,
"price": 140,
"item": {
"name": "10 coffrets",
"description": "+ 2 recharges",
"product": {
"name": "Coffret gris"
}
},
"amount": 280
},
{
"quantity": 2,
"price": 60,
"item": {
"name": "PACK N°1 comprenant :",
"description": "6 modèles",
"product": {
"name": "AfuBOX",
"description": "60,8 x 39,5 x 16,5 cm"
}
},
"amount": 120
}
],
"show": true,
"date": "10/06/2020",
"order_number": "105816",
"overallAmount": 680
}
you would need to set the 'show' property to false so that those that don't comply with what was entered in the search field would be hidden
Someone to make me see where my mistake is.
Thank you in advance
I have simplified the logic with a forEach and checking if the value I receive from the input contains any of the search criteria I wanted to apply.
I hope that this will help you to explain if you find yourself in a similar situation.
public changeSearch(searchTerm: string) {
this.searching = !!searchTerm;
if (!this.searching) {
this.orders.forEach(order => {
order.show = true;
});
return;
}
this.orders.forEach(order => {
order.show = true;
this.searchByProperty(order, searchTerm);
});
}
public searchByProperty(order, searchTerm) {
const id = (order.order_number + '');
const amount = (order.overallAmount + '');
order.transactions.forEach(items => {
const title = items.item.product.name.toLowerCase();
if (title.includes(searchTerm) || id.includes(searchTerm) || amount.includes(searchTerm)) {
order.show = true;
} else {
order.show = false;
}
});
}
I am trying to calculate the average duration for each stage. So in the array below - I should be able to get the average duration for 'test1', which would be 2.
jobs = [
{
"build_id": 1,
"stage_executions": [
{
"name": "test1"
"duration": 1,
},
{
"name": "test2"
"duration": 16408,
},
{
"name": "test3"
"duration": 16408,
},
]
},
{
"build_id": 2,
"stage_executions": [
{
"name": "test1"
"duration": 3,
},
{
"name": "test2"
"duration": 11408,
},
{
"name": "test3"
"duration": 2408,
},
]
}
]
My failed attempt:
avgDuration: function(jobs) {
let durationSum = 0
for (let item = 0; item < this.jobs.length; item++) {
for (let i = 0; i < this.jobs[item].stage.length; item++) {
durationSum += stage.duration
}
durationAverage = durationSum/this.jobs[item].stage.length
}
return durationAverage
What am I doing wrong? I'm not sure how to accomplish this since the duration is spread out between each job.
UPDATE:
This is return a single average for all stages rateher than per stage
<template>
<div class="stages">
<h3>
Average Duration
</h3>
<table>
<tbody>
<tr v-for="item in durations">
<td>
<b>{{ item.average}} {{ item.count }}</b>
// this returns only 1 average and 177 count instead of 10
<br />
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { calculateDuration } from "../../helpers/time.js";
import { liveDuration } from "../../helpers/time.js";
import moment from "moment";
export default {
name: "Stages",
data() {
return {
jobs: [],
durations: []
};
},
methods: {
avgDuration: function(jobs) {
var averageByName = {}; // looks like { 'name': { average: 111, count: 0 }}
for (var job of jobs) {
for(var stage of job.stage_execution) {
if (averageByName[stage.name] == null) { // we need a new object
averageByName[stage.name] = { average: 0, count: 0 };
}
// just name it so its easier to read
var averageObj = averageByName[stage.name];
// update count
averageObj.count += 1;
// Cumulative moving average
averageObj.average = averageObj.average + ( (stage.duration - averageObj.average) / averageObj.count );
console.log(averageObj.count)
}
}
return averageByName
},
},
created() {
this.JobExecEndpoint =
process.env.VUE_APP_TEST_URL +
"/api/v2/jobs/?limit=10";
fetch(this.JobExecEndpoint)
.then(response => response.json())
.then(body => {
for (let i = 0; i < body.length; i++) {
this.jobs.push({
name: body[i].job.name,
job: body[i].job,
stage_execution: body[i].stage_executions,
});
}
})
.then(() => {
this.$emit("loading", true);
})
.then(() => {
this.durations = this.avgDuration(this.jobs);
})
.catch(err => {
console.log("Error Fetching:", this.JobExecEndpoint, err);
return { failure: this.JobExecEndpoint, reason: err };
});
}
};
</script>
We can do this pretty simply and without overflow from having too many numbers by using a Cumulative moving average and a few loops.
Here is a line the relevant Wikipedia page on Moving Averages and the most relvant formula below.
I will not go into much detail with the above as there are a lot of documents describing this sort of thing. I will however say that the main reason to this over adding all the values together is that there is a far lower chance of overflow and that is why I am using it for this example.
Here is my solution with comments made in code.
var jobs = [ { "build_id": 1, "stage_executions": [ { "name": "test1", "duration": 1, }, { "name": "test2", "duration": 16408, }, { "name": "test3", "duration": 16408, }, ] }, { "build_id": 2, "stage_executions": [ { "name": "test1", "duration": 3, }, { "name": "test2", "duration": 11408, }, { "name": "test3", "duration": 2408, }, ] } ];
var averageByName = {}; // looks like { 'name': { average: 111, count: 0 }}
for (var job of jobs) {
for(var stage of job.stage_executions) {
if (averageByName[stage.name] == null) { // we need a new object
averageByName[stage.name] = { average: 0, count: 0 };
}
// just name it so its easier to read
var averageObj = averageByName[stage.name];
// update count
averageObj.count += 1;
// Cumulative moving average
averageObj.average = averageObj.average + ( (stage.duration - averageObj.average) / averageObj.count );
}
}
// print the averages
for(var name in averageByName) {
console.log(name, averageByName[name].average);
}
Let me know if you have any questions or if anything is unclear.
You could collect the values in an object for each index and map later only the averages.
var jobs = [{ build_id: 1, stage_executions: [{ name: "test1", duration: 1 }, { name: "test2", duration: 16408 }, { name: "test3", duration: 16408 }] }, { build_id: 2, stage_executions: [{ name: "test1", duration: 3 }, { name: "test2", duration: 11408 }, { name: "test3", duration: 2408 }] }],
averages = jobs
.reduce((r, { stage_executions }) => {
stage_executions.forEach(({ duration }, i) => {
r[i] = r[i] || { sum: 0, count: 0 };
r[i].sum += duration;
r[i].avg = r[i].sum / ++r[i].count;
});
return r;
}, []);
console.log(averages.map(({ avg }) => avg));
console.log(averages);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I've used Array.prototype.flatMap to flatten the jobs array into an array of {name:string,duration:number} object. Also, to make more solution a bit more dynamic the function takes in a field argument which returns the average for that specific field.
const jobs = [
{
"build_id": 1,
"stage_executions": [
{
"name": "test1",
"duration": 1,
},
{
"name": "test2",
"duration": 16408,
},
{
"name": "test3",
"duration": 16408,
},
]
},
{
"build_id": 2,
"stage_executions": [
{
"name": "test1",
"duration": 3,
},
{
"name": "test2",
"duration": 11408,
},
{
"name": "test3",
"duration": 2408,
},
]
}
];
const caller = function(jobs, field) {
const filtered = jobs
.flatMap((item) => item.stage_executions)
.filter(item => {
return item.name === field;
})
const total = filtered.reduce((prev, curr) => {
return prev + curr.duration;
}, 0)
return total / filtered.length;
}
console.log(caller(jobs, 'test1'))
console.log(caller(jobs, 'test2'))
console.log(caller(jobs, 'test3'))
In case you get the error flatMap is not a function. You can add this code snippet in your polyfill or at the top of your js file.
Array.prototype.flatMap = function(lambda) {
return Array.prototype.concat.apply([], this.map(lambda));
};
PS: for demostration, I obtained the flatMap implementation from here
I am trying to create an array that represents three different merchants which hold different prices for the same products(represented later in the code which ones).
My logic seems off and I would like help with one example on how this should be done correctly.
Attached is my code but please take notice only to the Merchantprices and getRecipeItems part.
JS
var main = function () {
var recipeType = {
0: {"name": "cocktail", "ingredients": ["Booz","Roofis","Green Stuff"]},
1: {"name": "appetizer", "ingredients": ["Some leaves","Some veggies", "I dunno toast","Cheese or whatever"]},
2: {"name": "main course", "ingredients": ["A dead animal","its blood", "some potatoes","love","asparagus"]} ,
3: {"name": "dessert", "ingredients": ["Dough","Some Sprinkly shit", "sugar","more sugar","cream shaboogy pop"]} ,
}
var Merchantprices = {
ampm:{"ingredientPrice":recipeType[0].ingredients = 20,"sumPrice":recipeType[0] = ingredientPrice * (recipeType[0].ingredients.length)},
haCarmel:{},
tivTaam:{},
}
function getRecipeItems() {
return recipeItems = [
{
"id": "recipe0",
"title": "Grasshopper Cocktail",
"img": "../images/grasshopper-cocktail.jpg",
"ingredients": recipeType[0].ingredients,
"instructions":"shaken not stirred",
"price": {"ampmPrice":Merchantprices[0].sumPrice,"haCarmelPrice":Merchantprices[1].sumPrice,"tivTaamPrice":Merchantprices[2].sumPrice},
"type" : recipeType[0].name,
},
{
"id": "recipe1",
"title": "Beef roast with veggies",
"img": "../images/beef-roast-with-veggies.JPG",
"ingredients": recipeType[2].ingredients,
"instructions":"stuff it good",
"price": 55,
"type" : recipeType[2].name,
},
{
"id": "recipe2",
"title": "Shrimp-Fried-Rice",
"img": "../images/Shrimp-Fried-Rice.jpg",
"ingredients": recipeType[1].ingredients,
"instructions":"extra MSG",
"price": 65,
"type" : recipeType[1].name,
},
{
"id": "recipe3",
"title": "Cupcake from hell",
"img": "../images/Cupcake-Idea-pics-200x150.png",
"ingredients": recipeType[3].ingredients,
"instructions":"death is inevitable",
"price": 15,
"type" : recipeType[3].name,
},
]
}
function createRecipeItem(recipeItem) {
var recipeElement = document.createElement('div');
recipeElement.setAttribute("id", recipeItem.id);
recipeElement.setAttribute("class", recipeItem);
recipeDetailsElement = document.createElement("div");
recipeDetailsElement.setAttribute("id", recipeItem.id+"_details");
recipeDetailsElement.appendChild(createDeleteRecipe(recipeItem));
recipeDetailsElement.appendChild(createRecipePic(recipeItem));
recipeDetailsElement.appendChild(createRecipeTitle(recipeItem));
recipePreperationElement = document.createElement("div");
recipePreperationElement.setAttribute("id", recipeItem.id+"_full_details");
recipePreperationElement.appendChild(createRecipeIngredients(recipeItem));
recipePreperationElement.appendChild(createRecipeInstructions(recipeItem));
recipePreperationElement.style.display = 'none';
recipeDetailsElement.appendChild(recipePreperationElement);
recipeElement.appendChild(createUndoDeleteRecipe(recipeItem));
recipeElement.appendChild(recipeDetailsElement);
return recipeElement;
}
function createUndoDeleteRecipe(recipeItem) {
var undoButton = document.createElement('span');
undoButton.setAttribute("id", recipeItem.id + "_undo");
undoButton.setAttribute("class", "fa fa-undo", "aria-hidden", "true");
$(undoButton).hide();
$(undoButton).click(() => {
onItemDeleteUndo(recipeItem);
});
return undoButton;
}
function createDeleteRecipe(recipeItem) {
var deleteButton = document.createElement('span');
deleteButton.setAttribute("class", "fa fa-times-circle", "aria-hidden", "true");
$(deleteButton).click(() => {
onItemDelete(recipeItem);
});
return deleteButton;
}
function onItemDelete(recipeItem) {
$('#'+recipeItem.id+'_details').hide();
$('#'+recipeItem.id+'_undo').show();
}
function onItemDeleteUndo(recipeItem) {
$('#'+recipeItem.id+'_details').show();
$('#'+recipeItem.id+'_undo').hide();
}
function createRecipeTitle(recipeItem) {
var div = document.createElement('div');
div.innerHTML = recipeItem.title;
return div;
}
function createRecipeInstructions(recipeItem) {
var div = document.createElement('div');
div.innerHTML = recipeItem.instructions;
return div;
}
function createRecipePic(recipeItem) {
var recipePic = document.createElement("img");
recipePic.setAttribute("src", recipeItem.img);
recipePic.setAttribute("class", "recipe");
$(recipePic).css('margin-top', '10px');
$(recipePic).click(() => {
$('#'+recipeItem.id+"_full_details").slideToggle();
});
return recipePic;
}
function createRecipeIngredients(recipeItem) {
var ingredients = document.createElement("ul");
ingredients.setAttribute("id", recipeItem.id + "_ingredients");
ingredients.className = "ingredientsList";
recipeItem.ingredients.forEach(ingredient => {
var li = document.createElement("li");
li.className = "ingredients";
li.setAttribute("type", "checkbox");
var checkbox = document.createElement("input");
checkbox.setAttribute("type", "checkbox");
li.appendChild(checkbox);
var ingredientElement = document.createElement("a");
ingredientElement.innerHTML = ingredient;
li.appendChild(ingredientElement);
ingredients.appendChild(li);
})
return ingredients;
}
recipeItems = getRecipeItems();
var mainContainer = document.getElementsByClassName('mainContainer');
recipeItems.forEach(recipeItem => {
mainContainer[0].appendChild(createRecipeItem(recipeItem));
});
};
var recipeItems;
var Merchantprices;
$(document).ready(main);
Ok, so I think I got want you meant to do. Here are 2 solutions :
Keep all in one place
function getRecipeItems() {
return recipeItems = [
{
"id": "recipe0",
// ...
"price": {
default: 8,
ampm: 10,
// -- haCarmel: 12, -- Let's omit this one
tivTaam: 15,
get: function( merchant ) {
return this[merchant] ? this[merchant] : default;
}
}
},
// ...
]
}
// ---------------------------------------
// Usage
// ---------------------------------------
// Result : 8 (default price, as you didn't specify the merchant).
getRecipeItems()[0].price.get();
// Result : 10.
getRecipeItems()[0].price.get("ampm");
// Result : 8 (default, as you didn't set this value).
getRecipeItems()[0].price.get("haCarmel");
Merchant's magic calculations
You could also set a default price, but send it to the merchant and alter it.
// Price
"price": {
default: 8,
get: function( merchant ) {
return Merchants[ merchant ]
? Merchants[ merchant ].getPrice( this.default )
: this.default;
}
}
// Merchants
Merchants {
ampm: {
//...
getPrice: function( price ){
return price + itemRarity - discount + etc;
}
},
// ...
};
In both cases, ...
You should create an object for the Merchant, RecipeItem and RecipeItemPrice. Your code will be more clean and you wouldn't create an instance of the get() function each time you create a price. Well, you should do that with ALL your game objects. :)
// Price
var RecipeItemPrice = function( value, ... ) {
this.default = value;
};
RecipeItemPrice.prototype.get = function() {
// For example, if you take the second choice :
return Merchants[ merchant ]
? Merchants[ merchant ].getPrice( this.default )
: this.default;
};