Json Data :
{
"food": {
"rates": {
"defaultRates": {
"cardRate": 600,
"discountedRate": 500
},
"otherRates": [
{
"cardRate": 600,
"discountedRate": 400,
"fields": [
{
"name": "Quantity",
"min": 3,
"max": 6
}
],
"name": "3-6 Quantity"
},
{
"cardRate": 600,
"discountedRate": 300,
"fields": [
{
"name": "Quantity",
"min": 7
}
],
"name": "7+ Quantity"
}
]
},
"details" : {
"name" : "Something"
}
}
JS Code:
$scope.food = angular.copy(JSONObject); // Copied JsonObject
$scope.defaultRates = angular.copy($scope.food.rates.defaultRates);
$scope.otherRates = angular.copy($scope.food.rates.otherRates);
$scope.quantity = 4;
angular.forEach($scope.otherRates, function (otherRate) {
angular.forEach(otherRate.fields, function (field) {
if($scope.quantity >= field.min){
if(field.max) {
if($scope.quantity <= field.max){
$scope.discountedRate = angular.copy(otherRate.discountedRate);
}
} else {
$scope.discountedRate = angular.copy(otherRate.discountedRate);
}
} else {
$scope.discountedRate = angular.copy($scope.defaultRates.discountedRate);
}
})
});
If I console the $scope.discountedRate I'm getting the 7+ quantity rate. I want to get the $scope.discountedRate according to the $scope.quantity I have given.
So, How to get the discounted rate from the json data by comparing the quantity of the food.
You need to iterate over otherRates as follows.
var qty = what ever the user selects
var matched = {};
angular.forEach(food.otherRates, function(otherRate){
angular.forEach(otherRate.fields, function(field){
if(field.min <= qty && field.max >= qty)
matched = otherRate;
else if(field.min <= qty)
matched = otherRate;
});
});
console.log(matched);
//matched is the other Rate
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 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 have JSON data which is structured as below. Intension is to look up a specific datapoint, e.g. annual profit, which is 5000.
I want to do this by finding the column by name, e.g. "profit", identify the column index (3 in the example), and then use the column index to select the nth (3rd) element in the second node ("annual") of the "data" array.
How can I do this using the findIndex() function in Javascript (see the key part of my code below)?
JSON data:
{
"datatable": {
"data": [
[
"AAPL",
"quarterly",
1000,
2000
],
[
"AAPL",
"annual",
5000,
10000
]
],
"columns": [{
"name": "ticker"
"type": "String"
},
{
"name": "timedim"
"type": "String"
},
{
"name": "profit",
"type": "Integer"
},
{
"name": "revenue",
"type": "Integer"
}
]
}
}
JavaScript code:
// daten contains the "data" array of the JSON dataset
// spalten contains the "columns" array of the JSON dataset
var i = spalten.findIndex(obj => obj.name == "profit");
output += '<p>Annual profit AAPL: ' + daten[i] + '</p>';
elroot.innerHTML += output;
You have 2-dimensional array, so, you need two indexes:
const json = {
"datatable": {
"data": [
[
"AAPL",
"quarterly",
1000,
2000
],
[
"AAPL",
"annual",
5000,
10000
]
],
"columns": [{
"name": "ticker",
"type": "String"
},
{
"name": "timedim",
"type": "String"
},
{
"name": "profit",
"type": "Integer"
},
{
"name": "revenue",
"type": "Integer"
}
]
}
}
var profitIndex = json.datatable.columns.findIndex(item => item.name == 'profit');
var annualIndex = json.datatable.data.findIndex(array => array.indexOf('annual') > -1);
var annualProfit = json.datatable.data[annualIndex][profitIndex];
If you need a function, it could look like below:
var getValueFromJson = function (json, columnName, dataMarker) {
var columnIndex = json.datatable.columns.findIndex(item => item.name == columnName);
var dataMarkerIndex = json.datatable.data.findIndex(array => array.indexOf(dataMarker) > -1);
if (columnIndex < 0 || dataMarkerIndex < 0) {
return null;
}
return json.datatable.data[dataMarkerIndex][columnIndex];
}
console.log(getValueFromJson(json, 'profit', 'quarterly'));
console.log(getValueFromJson(json, 'profit', 'annual'));
console.log(getValueFromJson(json, 'revenue', 'quarterly'));
console.log(getValueFromJson(json, 'revenue', 'annual'));
Above code prints:
> 1000
> 5000
> 2000
> 10000
Based on the JSON structure you've given, the following will work. Writing a function would be good if you want to get specific profit based on parameters.
var output = ""
function getProfit(type="annual", column=2) {
var arrForType = yourData.datatable.data.find(arr => arr.indexOf(type) !== -1);
return arrForType[column];
}
var i = yourData.datatable.columns.findIndex(obj => obj.name == "profit");
output += '<p>Annual profit AAPL: ' + getProfit("annual", i) + '</p>';
document.body.innerHTML += output;
You don't need findIndex - just use find and includes like so:
const data = {
"datatable": {
"data": [
[
"AAPL",
"quarterly",
1000,
2000
],
[
"AAPL",
"annual",
5000,
10000
]
],
"columns": [{
"name": "ticker",
"type": "String"
},
{
"name": "timedim",
"type": "String"
},
{
"name": "profit",
"type": "Integer"
},
{
"name": "revenue",
"type": "Integer"
}
]
}
};
function findValue(type) {
return data.datatable.data.find(e => e.includes(type))[2];
}
console.log(findValue("annual"));
console.log(findValue("quarterly"));
This is the basic idea, then if you need to scale obviously you'll need to do this in a nicer way.
let output = '';
// Searches the desired index (refactor as needed)
const index = spalten.findIndex(obj => obj.name == "profit")
// Extract all the profits (if you dont need all just select the desired one)
daten.map(item => output += `<p>${item[1]} profit ${item[0]}: ${item[index]}</p>`)
Got an object containing a user id for each user and prices, would like to create a new object/array for each user (no duplicates) and be able to calculate the total sum of price for each user. Tried using Object.values() with map and filter but can't get it to work properly
{
"data": {
"item1": {
"price": "20",
"user": "user1"
},
"item2": {
"price": "10",
"user": "user2"
},
"item3": {
"price": "50",
"user": "user1"
}
}
}
Output something like this:
{
"users": {
"user1": {
"totalSum": "70",
},
"user2": {
"totalSum": "10",
}
}
}
I'm thinking about using map to present the "users"-data, maybe an array would be better?
Using function reduce.
Important: The attribute price is a String, this approach uses object Number to convert that value to a numeric one.
var obj = { "data": { "item1": { "price": "20", "user": "user1" }, "item2": { "price": "10", "user": "user2" }, "item3": { "price": "50", "user": "user1" } }};
var result = Object.keys(obj.data).reduce((a, k) => {
if (a.users[obj.data[k].user]) {
a.users[obj.data[k].user].totalSum += Number(obj.data[k].price);
} else {
a.users[obj.data[k].user] = {
"totalSum": Number(obj.data[k].price)
}
}
return a;
}, {
'users': {}
});
console.log(result);
.as-console-wrapper {
max-height: 100% !important; top: 0;
}
You could leverage ```reduce, more information here
code (haven't tried this)
var data = JSON.parse(mainObj).data;
var usersWithTotalExpenditure = Object.keys(data).reduce(function(result, key) {
var currentItem = data[key];
var useName = currentItem.user;
var price = Number(currentItem.price);
if (userName in result) {
result[userName].totalSum += price;
} else {
result[userName] = {
totalSum: price
};
}
return result;
}, {});
var resultObject = {
users: usersWithTotalExpenditure
}
You can use a forEach loop. This relies on Javascripts powerful OR operator, which coerces the first half of the expression to false if the current user's price is not defined (meaning it is a user the loop hasn't encountered before)
`c is your initial object's data, output is empty object`
const c = obj.data;
var output = {};
Object.keys(c).forEach((val) => {
output[c[val]["user"]] = parseInt(output[c[val]["user"]]) + parseInt(c[val]["price"]) || parseInt(c[val]["price"]);
})
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;
};