Separating of Data and Function in Java - javascript

I want to initialize a deck of individual cards in Java. This is my approach so far:
public ArrayList<Card> initDeck() {
ArrayList<Card> cardDeck = new ArrayList<Card>(24);
cardDeck.add(new Card("Emperor Augustus", 20.1, 40, 4.1, 300000, POWER_AND_INFLUENCE.VERY_HIGH));
cardDeck.add(new Card("Jeff Bezos", 96, 22, 59.7, 268000, POWER_AND_INFLUENCE.HIGH));
cardDeck.add(new Card("Bill Gates", 83.7, 41, 73, 112388, POWER_AND_INFLUENCE.MEDIUM));
return cardDeck;
}
This is a lot of repetition IMO. Also I want to separate the data from function.
Is it possible to export the elements I want to add into cardDeck, i.e. new Card(...) into a separate file?
In JavaScript you would make it for example like this:
JSON-File:
{
data: [{
name: "asdf",
economy: 123,
yearsInPower: 4
}, {
name: "bsdf",
economy: 3,
yearsInPower: 10
}, {
name: "csdf",
economy: 43,
yearsInPower: 5
}]
}
JS-File:
const cards = require("./cards.json").data;
function initDeck(cards) {
const cardDeck = [];
for (let i = 0; i < cards.length; i++) {
cardDeck.push(cards[i]);
}
return cardDeck;
}
let cardDeck = initDeck(cards);
I've looked into other implementation of the initialization of cards in Java. But all the examples assumes a logical order of the cards, e.g. 2,3,4...Jack, Queen, King, Ace. But in my example the cards don't follow any logical order.

There are several ways that you can separate data from code (like loading from files, database, etc..).
If you wanted to load data from JSON file, then you can use Jackson library to read the data from JSON and convert to Java objects (deserialization) as shown below:
public List<Card> initDeck() throws Exception {
ObjectMapper mapper = new ObjectMapper();
Card[] staff = mapper.readValue(new File("C:\\cards.json"), Card[].class);
List<Card> cardDeck = Arrays.asList(staff);
return cardDeck;
}
Also, as a side note, remember that it is always a best practice to code for interfaces List<Card> as return types (shown above) rather than concrete classes like `ArrayList, you can look here on the same subject.

Related

Is there a way to Camel Case the column names returned from PostgreSQL using pg-promise?

When we execute queries to our PostgreSQL Database and receive responses, we then pass these responses to our clientside to display/work with.
Example:
const response = [
{
first_name: 'Bob',
last_name: 'English',
title: 'The Dude',
},
{
first_name: 'Harry',
last_name: 'Smith',
title: 'Unknown',
},
];
Our app then has to map over this and rename the keys in a rather inefficient and verbose manner. Is there a better way? Perhaps using pg-promise?
Worth noting we also have to convert back when we send the data as an UPDATE to the DB.
It's worth noting we are not looking to use a ORM like Objection or a query builder like Knex.
Event receive in the API offers a usable example of how this can be done:
// Example below shows the fastest way to camelize all column names.
// NOTE: The example does not do processing for nested JSON objects.
const initOptions = {
// pg-promise initialization options...
receive(e) {
camelizeColumns(e.data);
}
};
function camelizeColumns(data) {
const tmp = data[0];
for (const prop in tmp) {
const camel = pgp.utils.camelize(prop);
if (!(camel in tmp)) {
for (let i = 0; i < data.length; i++) {
const d = data[i];
d[camel] = d[prop];
delete d[prop];
}
}
}
}
It also has been discussed in various issues on the project in the past, and documented by other developers, like in this article, which is a good way to get started with it. UPDATE: That article is obsolete for pg-promise v11.
It is a universal approach that works for all types of queries, including streams.
UPDATE
The example above has been updated to use pg-promise v11 or later.

Strongly typed Immutable.js Records in TypeScript

I'm unable to find a good resource for this question. Essentially I want to describe types for my data using an interface in TypeScript, but my data is Immutable.js records which appears to complicate matters, please see my example below.
interface tree extends Immutable.Map<string, any> {
readonly id: number,
readonly type: number
}
let trees = Immutable.List<tree[]>([
Map<tree>({
id: 101,
type: 1
}),
Map<tree>({
id: 201,
type: 3
})
])
Questions with the above:
Why do I have to repeat the type of each map in my list? Shouldn't the type be simply be declared by the <tree[]> when creating the list? And then any Map added to the list be type checked against this?
At present this example errors, stating that "property 'id' is incompatible with index signature. Type 'number' is not assignable to type 'tree'. Which makes sense! However, reading the documentation, I can't work out how to get it to work? Reading the docs it states I need an ID but I want an array of maps, my signature in this case is just standard array ID's if I not much mistaken?
I've been working on this for days and I simply can't get it to work, it should be this simple according to everything I've read.
Any help would be greatly appreciated.
You are creating a List of arrays of trees, which is an extended Map. This is what it should look like:
let trees = Immutable.List<tree[]>(
[ // List
[ // Array
<tree>Immutable.Map<any>({
id: 101,
type: 1
}),
<tree>Immutable.Map<any>({
id: 201,
type: 3
})
]
]
);
Answering your questions:
You are not repeating the type of each map. Actually, you are calling a method Map that builds a map from an object. I added the <tree> cast because it is an array of trees, not maps.
You are trying something like:
var singleTree: tree = Immutable.Map<tree>(
{ id: 101, type: 1 }
);
But your tree is a map of the any type. So, this is the right syntax:
let singleTree: tree = <tree>Immutable.Map<any>(
{ id: 101, type: 1 }
);
For the code above, we can simplify and force a type check if we create a tree function to wrap the Map function, so, the final solution would be:
function tree(obj: { [key: string]: any, id: number, type: number }): tree {
return <tree>Immutable.Map<any>(obj);
}
let trees = Immutable.List<tree[]>(
[ // List
[ // Array
tree({
id: 101,
type: 1
}),
tree({
id: 201,
type: 3
})
]
]
);

Javascript enum with multiple values and value types

I'm trying to make a system which reads Dota 2 hero data, in this system I have to store a lot of data about each hero (strength gain, int gain, agility gain)(float) and also what their primary attribute is.
This is what I have so far:
const Heroes = {
Abaddon: 'Strength',
Alchemist: 'Strength',
AncientApparition: 'Intelligence',
AntiMage: 'Agility',
ArcWarden:'Agility',
Axe:'Strength',
}
tried this:
const Heroes = {
Abaddon: ('Strength','3.4', '2.4', '1.8', true),
Alchemist: ('Strength','2.8', '2.3', '1.6', true),
}
console.log(Heroes.Abaddon)
The output was just the last value (true)
You could get creative and use Enums like Java uses them, for more than a way to rename integers like many other languages. Or you could simply use a standard JavaScript object like this:
const Heroes = {
Abaddon: {
primaryAttribute: 'Strength',
attributeGains: {
strength: 3.4,
intelligence: 2.4,
agility: 1.8
}
},
Alchemist: {
primaryAttribute: 'Strength',
attributeGains: {
strength: 2.8,
intelligence: 2.3,
agility: 1.6
}
}
};
Accessing the values are as simple as you would expect.
console.log(Heroes.Abaddon.primaryAttribute);
console.log(Heroes.Alchemist.attributeGains.agility);
I'm not sure why you are in need of an Enum specifically, but in the end, you will be making a complex but standard JavaScript object.
You can't do this with JavaScript. The parentheses are just extras. Try using arrays:
const Heroes = {
Abaddon: ['Strength','3.4', '2.4', '1.8', true],
Alchemist: ['Strength','2.8', '2.3', '1.6', true],
}
console.log(Heroes.Abaddon)

Storing static and common data in React Native

Hello I am creating a dictionary app in React Native and I simply want to store an array of JSON blobs that would hold the definitions of each word.
I would very much like to avoid having to hardcode the data and want my code to be DRY!
Sample JSON blob:
[
{
"word": "triangle",
"definition": "a plane figure with three straight sides and three angles.",
"type": "noun"
},
{
"word": "square",
"definition": "a plane figure with four equal straight sides and four right angles.",
"type": "noun"
},
{
"word": "circle",
"definition": "a round plane figure whose boundary (the circumference) consists of points equidistant from a fixed point (the center).",
"type": "noun"
}
]
What is the best strategy to store this data so that it is:
Can be bookmarked by the user
Clean and easy to change and separated from other files
How it can be accessed by my React components
I think Relational DataBases are the best approach but I have difficulty figuring out how I would seed the database with data. And which library on React Native to use for a Relation Database.
Thank you for reading my question.
You can do what you are describing using Realm with the following schema:
let EntrySchema = {
name: 'Entry',
primaryKey: 'word',
properties: {
word: 'string',
definition: 'string',
type: 'string'
}
};
let BookmarkListsSchema = {
name: 'BookmarkList',
properties: {
bookmarks: {type: 'list', objectType: 'Entry'}
}
};
let realm = new Realm({schema: [EntrySchema, BookmarkListsSchema]});
You can pre-populate a Realm file with all of your dictionary entries and bundle it with your app, or alternatively you could download this file or JSON and initialize your db when starting the app.
To create/add bookmarks:
// create your list once
var bookmarkList;
realm.write(() => {
bookmarkList = realm.create('BookmarkList');
});
// add entry for 'triange' to bookmarks
realm.write(() => {
let triangeEntry = realm.objectForPrimaryKey('Entry', 'triangle');
bookmarkList.bookmarks.push(triangleEntry);
});

Knockout JS not setting all members observable

What I am trying to do is to get data from the server and then putting it all in an observable and then make all the properties observable. The issue I am facing is that it does not make all my properties observable and I need them all to be observable as sometimes depending on the data it makes some properties observable and sometimes it doesn't.
var viewModel = this;
viewModel.Model = ko.observable();
viewModel.SetModel = function (data) {
viewModel.Model(ko.mapping.fromJS(data));
}
The data that I am receiving from the server is like this for example: normaldata,items(this is an array with unknown number of elements).
so if i try to access data like viewModel.Model().Items[0]().Layer() i sometimes have Layer as a function and sometimes it is a normal element with observable elements.I want all my objects inside Items to have Layer as a function.
Server data example:
Name: "test"
Items: [Layer[ID: 132]]
In this example Name,Items and ID are observable but Layer is not.
Fiddle example:
jsfiddle.net/98dv11yz/3
So the problem is that sometimes the layer is null resulting in ko making the property observable but sometimes that property has id and ko makes only the child elements observable. The problem is that i have if's in the code and i want it to be a function so i can always reffer to it as layer() because now it is sometimes layer or layer()
An explenation for what's happening:
When the ko.mapping plugin encounters an object in your input, it will make the object's properties observable, not the property itself.
For example:
var myVM = ko.mapping.fromJS({
name: "Foo",
myObject: {
bar: "Baz"
}
});
Will boil down to:
var myVM = {
name: ko.observable("Foo"),
myObject: {
bar: ko.observable("Baz")
}
}
and not to:
var myVM = {
name: ko.observable("Foo"),
myObject: ko.observable({
bar: ko.observable("Baz")
})
}
The issue with your data structure is that myObject will sometimes be null, and sometimes be an object. The first will be treated just as the name property in this example, the latter will be treated as the myObject prop.
My suggestion:
Firstly: I'd suggest to only use the ko.mapping.fromJS method if you have a well documented and uniform data structure, and not on large data sets that have many levels and complexity. Sometimes, it's easier to create slim viewmodels that have their own mapping logic in their constructor.
If you do not wish to alter your data structure and want to keep using ko.mapping, this part will have to be changed client-side:
Items: [
{ layer: {id: "0.2"} },
{ layer: null}
]
You'll have to decide what you want to achieve. Should the viewmodel strip out the item with a null layer? Or do you want to render it and be able to update it? Here's an example of how to "correct" your data before creating a view model:
var serverData = {
Name: "Example Name",
Id: "0",
Items: [
{layer: {id: "0.2"} },
{layer: null}
]
};
var correctedData = (function() {
var copy = JSON.parse(JSON.stringify(serverData));
// If you want to be able to render the null item:
copy.Items = copy.Items.map(function(item) {
return item.layer ? item : { layer: { id: "unknown" } };
});
// If you don't want it in there:
copy.Items = copy.Items.filter(function(item) {
return item.layer;
});
return copy;
}());
Whether this solution is acceptable kind of relies on how much more complicated your real-life use will be. If there's more complexity and interactivity to the data, I'd suggest mapping the items to their own viewmodels that deal with missing properties and what not...

Categories