Is this a reasonable class inheritance approach? [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
In trying to learn more about JavaScript (Google Apps Script flavor), I created an object structure that I think might be useful for a number of projects. My main goals for this little demonstration are:
learn the use objects (classes) and inheritance
minimize calls to the Spreadsheet Service by summoning a data table once per sheet
use the Named Ranges on the spreadsheet to access the data in the table
The code below seems successful, but surely can be improved. A couple of major questions are:
Is there a better way to accomplish the inheritance of methods and properties than this?
The Spreadsheet() function gets run for each of the Sheet objects, resulting in the environment structure having separate "ss" and "namedRangeList" properties in each of the Sheet objects. Is this normal and expected? Or is there a better approach to avoid this duplication? Or, is JavaScript just recording pointers to a single instance of these objects, so it really doesn't matter that they appear to be duplicated?
Because they are common to and the same for all of the Sheets, I had expected "ss" and "namedRangeList" to show up only at the Environment level and therefore available to the Sheets through inheritance rather than duplication.
What other changes or approaches would improve my fledgling use and understanding of classes and objects?
Here is a stripped down version of my code that preserves the essence of the structure but leaves out comments, error handling, and other functionality.
function Environment() {
this.title = 'Car & Driver';
this.ui = SpreadsheetApp.getUi();
this.dd = new Drivers();
this.cc = new Cars();
}
function Spreadsheet() {
this.ss = SpreadsheetApp.getActiveSpreadsheet();
this.namedRangeList = {};
var namedRanges = this.ss.getNamedRanges();
for (var i = 0; i < namedRanges.length; i++) {
var range = namedRanges[i].getRange();
this.namedRangeList[namedRanges[i].getName()] = {
sheet: range.getSheet().getSheetName(),
row: range.getRow(),
column: range.getColumn(),
rowCount: range.getNumRows(),
columnCount: range.getNumColumns(),
}
}
}
Spreadsheet.prototype = Object.create(Environment.prototype);
function Sheet() {
Spreadsheet.call(this);
this.sheet = this.ss.getSheetByName(this.sheetName);
this.data = this.sheet.getDataRange().getValues();
}
Sheet.prototype = Object.create(Spreadsheet.prototype);
function Cars() {
this.sheetName = 'Cars';
this.abbreviation = 'cc';
Sheet.call(this);
}
Cars.prototype = Object.create(Sheet.prototype);
function Drivers() {
this.sheetName = 'Drivers';
this.abbreviation = 'dd';
Sheet.call(this);
}
Drivers.prototype = Object.create(Sheet.prototype);
Sheet.prototype.idxOf = function(namedRange) {
return (this.namedRangeList[namedRange].rowCount == 1) ?
this.namedRangeList[namedRange].row - 1 :
this.namedRangeList[namedRange].column - 1;
}
function test_Environment() {
var env = new Environment();
env.ui.alert('The third driver is ' +
env.dd.data[3][env.dd.idxOf('ddFirst')] + ' ' + env.dd.data[3][env.dd.idxOf('ddLast')] + '.');
var tests = [
['dd', 2, 'ddLast' , 'Bailey' ],
['dd', 3, 'ddLicense' , 'pro' ],
['cc', 1, 'ccRadio' , 122.5 ],
['cc', 4, 'ccModel' , 'Corvette'],
];
tests.forEach(function(t) {
var v = env[t[0]].data[t[1]][env[t[0]].idxOf(t[2])];
Logger.log( (v == t[3]) + ': ' + (t[0] == 'dd' ? 'Driver ' : 'Car ') +
t[1] + ' ' + t[2].slice(2) + ' is ' + v );
});
env.ui.alert(env.title + ' is all done');
}

You can take a look at the mozilla page of JavaScript Objects.
Also there are a tons of questions in stack about this issue about inheritance in javascript.
Also as talked in the comments if you want someone to criticize your code take a look at Code Review

Related

Javascript:-Embedded "For Loop" is not working in HTML [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I was trying to implement a for loop embedded in HTML to print the values in an array. This is what I did:
var arr = [];
for (var id in order.cart.items) {
arr.push(order.cart.items[id]);
}
console.log()
let mailOptions = {
from: "John Doe"+"<johndoe#gmail.com>", // TODO: email sender
to:email , // TODO: email receiver
subject: 'Order Confirmation',
html: "<script>"+"<br>"+ "var i;"+ "<br>" +
"for("+"i="+0+";"+"i<"+arr.length+";"+"i++" +")"+"{"+arr[i].item.title+"}"+"<br>"+"</script>"}
The problem is with the html part in mailOptions. The for loop does not seem to be working. The array is getting values, but the error shown is: i is not defined. How can I do this? What is wrong in the above syntax? The array is working properly. If I put arr[0] or arr[1] in place of arr[i], everything works properly
The only instance of i I see in this code is +arr[i].item.title+.
But you don't have the variable i declared inside this script that's making this mailOptions, only inside the script tag you're trying to write inside the mailOptions html.
Maybe I'm missing something or we're missing part of the code ( is this code part of some other for-loop that's not shown? Otherwise it seems logical to me that the i is not defined error is about this script, not the embedded one.
EDIT:
Alot of things do not make sense here, since arr and i are not part of the same script, but i think you might be looking for this instead of embedding a script tag:
var order = {
cart: {
items: {
id_123: { item: { title: "val123" }},
id_456: { item: { title: "val456" }},
id_789: { item: { title: "val789" }}
}
}
};
var arr = [];
for (var id in order.cart.items) {
arr.push(order.cart.items[id]);
}
var email = 'a#a.vcom';
var html = '';
var i;
for ( i=0;i<arr.length;i++) {
html += arr[i].item.title + '<br>';
}
let mailOptions = {
from: "John Doe"+"<johndoe#gmail.com>", // TODO: email sender
to: email , // TODO: email receiver
subject: 'Order Confirmation',
html: html
};
console.log( mailOptions );
Is this what you're after? Including all the order items inside the email as HTML? instead of trying to embed a script tag?
I'm not sure, but i can imagine it has trouble parsing your embedded script. What is it you are trying to achieve? If you want to create a list of items, why don't you create a function instead, that returns a list of items in plain html?

Discord.js searching on key terms

I'm trying to create a Discord bot for trading within certain games. So far I have most of the basic commands working--!create creates a trade listing in an SQL database, !find finds one--but it only finds it on the exact same word. What I'm trying to do is make the search less specific so the terms don't have to be exactly equal to show results.
My current code is pretty convoluted and, needless to say, very broken:
var searchTerms = args[1].split(" ");
var output = {};
for (var id in userData) {
for (var offer in userData[id].offers) {
var score = 0;
for (var key in searchTerms) {
if (offer.includes(key)) {
score ++;
}
}
if (score >= searchTerms.length / 2) {
output[id] = userData[id].offers[offer] + " - " + ((score / searchTerms.length) * 100) + "%";
}
}
}
if (output == {}) {
bot.sendMessage({
to: channelID,
message: 'No matching offers found.'
});
} else {
msg = ""
for (id in output) {
msg += '<#' + id + '> - ' + output[id] + " "
}
bot.sendMessage({
to: channelID,
message: Object.keys(output).length + ' offers found: ' + msg
});
}
I'm new to Javascript so I'm not really sure how to get this working. Any tips are appreciated, thanks!
It looks like what you're trying to implement is an mechanism called Fuzzy Search, which user can find similar results using typo or approximate strings.
( Reference: https://en.wikipedia.org/wiki/Approximate_string_matching )
It not really an easy feature for a programming beginner to implement on your own, either the database have to support some kind of fuzzy query, or you'll have to get all the data from database first, and use a JavaScript fuzzy search library to accomplish that.
If you still want to do it, I recommend using Fuse.js, which is able to accomplish fuzzy search in a few lines
//list to be searched
var books = [{
'ISBN': 'A',
'title': "Old Man's War",
'author': 'John Scalzi'
}, {
'ISBN': 'B',
'title': 'The Lock Artist',
'author': 'Steve Hamilton'
}]
// init the search
var options = {
keys: ['title', 'author'],
id: 'ISBN'
}
var fuse = new Fuse(books, options)
fuse.search('old')
// result
[
"A"
]
Fuzzy search is a complex computer science problem, if you want to know more about it and how Fuse.js is implemented, here are a few useful links
An intro to fuzzy string matching
source code of Fuse.js
bitap algorithm (used by fuse.js)

How can I dynamically build Functions in javascript

Firstly, I am new to javascript.
I am trying to build a webpage to keep track of some numbers for a game.
The game involves keeping track of statistics for a character, in two sections. 1) Base Statistics (Strength, Dexterity ...) and 2) Skills (Drive car, sword, electronics repair, painting ...)
I have a PHP script to call the Stats, with input boxes to adjust them, and a JavaScript code to add them up as they are altered. This works fine for the 8 Stats, but I have written a separate function for each (getStrength, getDexterity ...), with a getTotal function that sums them and displays.
I would like to use a similar process for the 150 Skills (~10 categories with ~15 skills each), without writing 150 separate functions (getDrive, get sword, get painting ...)
I can pull the Skill List from database. Can I run a loop over this to create the required functions?
This is how I would code such things. There's downsides to this approach as well (it doesn't minify well and such), but at least you don't have to define 200 functions that all do the same thing: return a property of your character:
var Charcter = function Character( name ) {
this.id = {
'name' : name,
'class' : 'ranger',
'level' : 1
}
this.stats = {
'str' : 10,
'dex' : 18,
'con' : 14,
'int' : 10,
'wis' : 16,
'cha' : 16
};
this.skills = [
'archery',
'horsemanship'
];
};
Character.prototype = {
'get' : function get( subType, fieldName ) {
return this[subType][fieldName];
}
};
var shilly = new Character('shilly');
console.log('I am a ' + shilly.get('id', 'class') + ' of level ' + shilly.get('id', 'level') );
console.log('My second skill is ' + shilly.get('skills', 1) + '.' );

Prototypes etc in Angular JS [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Should you you use classes, prototypes etc in Angular JS? I learned Angular JS before I learned Javascript (bad idea). Now I've started to read some about OOP in javascript. I'm very confused at the moment.
I have an example. It's a service. It has some data from server and some input from user. It runs som logic and populate the object which is then viewed for the user.
Option 1. Just an object. I've removed most of the code so it's more a pseudo code. This is the way you see in most examples and tutorials.
angular.module('calculationServices', ['ngResource']).
factory('CalculationFactory', function(UnitsFactory){
var calculations = {
mainCalculation: function(sizes, pipe, temperature){
if(sizes === null || temperature === null){
return;
}
var rawness = pipe.rawness;
var mediaDensity = temperature.density;
var results = [],
nrOfSizes = sizes.length;
for(var i = 0;i<nrOfSizes;i++){
var flow = this.input.flow.valueInSIunit;
var velocitySiUnit = this.velocityFN(sizes[i].innerdiameter/1000,flow);
var pressureDropInSiUnit = this.pressureDropFN(velocitySiUnit,mediaDensity, frictionFactor, sizes[i].innerdiameter/1000);
results.push({
size:sizes[i].nominalsize
innerDiameter:sizes[i].innerdiameter,
velocity:{
siUnit:velocitySiUnit,
userUnit:velocityUserUnit
}
});
}
return results;
},
powerFN: function(flow, cp, density, deltaT){
var power = flow * cp * deltaT * density;
return power;
},
velocityFN: function(innerDiameter, flow){
var area = Math.PI * Math.pow((innerDiameter) * 0.5 ,2);
return flow / area;
},
input: { //Input is hooked up to my $scope
flow:{
valueInSIunit: 0.00075,
value:0.75,
unit: 'l/s'
}
},
};
return calculations;
})
})
Option 2 Or. should I use classes, instantiating, prototypes etc. Something like this:
factory('CalculationFactory', function(UnitsFactory){
function PipeCalculations(params){
this.flow = params.flow;
this.pipe = params.pipe;
this.sizes = params.sizes;
}
PipeCalculations.prototype.velocityFN = function(flow, innerDiameter){
var area = Math.PI * Math.pow((innerDiameter) * 0.5 ,2);
return flow / area;
}
PipeCalculations.prototype.createPipeCalculationObjects = function(sizes){
var results = [];
var nrOfSizes = sizes.length;
var velocitySiUnit = this.velocityFN(sizes[i].innerdiameter/1000,flow);
for(var i = 0;i<nrOfSizes;i++){
results.push({
size:sizes[i].nominalsize,
velocity:{
siUnit:velocitySiUnit
}
});
}
return results;
};
var pipeCalculations = new PipeCalculations({
flow: { //Should this be hooked up directly to my scope?
valueInSiUnit: 55,
valueInUserUnit: 0.75
},
pipe: 0, //Data feed from controller
sizes: 0
});
pipeCalculations.velocity = pipeCalculations.velocityFN(pipeCalculations.flow.valueInSiUnit, 25);
pipeCalculations.output = pipeCalculations.createPipeCalculationObjects(pipeCalculations.sizes);
return pipeCalculations;
})
Is there a clear right and wrong here? I did option one first. It was very easy and everything worked smoothly. But it didn't feel quite "OOP". However, option 2 is much harder for me because it's difficult to find decent examples. Also, with option one I can simply attach my scope to my model and everything is updated automatically. But how do i do it correctly with option 2? Should i instantiate from my controller?

online data storage alternative to SQL [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I've made a very very simple quiz game in my spare time and basically the quiz poses a number of questions and when the quiz is done you get a score. I'd like for this score to be saved but I don't want to use a database to store them. Is it possible to store it in a .txt file or something like that? I have ONLY used html and JavaScript for this game (and some CSS) but I haven't used PHP and would like to avoid it at all costs.
If you are just storing the score to reuse it on the page for that user, you can store it in a cookie. This can be done with JavaScript. http://www.quirksmode.org/js/cookies.html Be aware that a user can modify the cookie to change his saved score.
If you want to store the value on the server, you will need to use some programming language on the server. There are many alternatives to PHP (e.g.: Python, Ruby, Perl).
You can use Local Storage Local Storage
to save score
I haven't used PHP and would like to avoid it at all costs.
So you want to store data in a text file but you don’t want to use PHP? How do you expect to save the data?
I would then recommend you use a pre-packaged CMS framework like WordPress. Yes it uses MySQL & PHP, but you do not have to be a PHP or MySQL expert to use it. And for what you describe, it sounds like this would be the best way for you to implement this application without learning much beyond WordPress basics.
You could use a modification of the function I used on my website, I guess. You end up storing a bunch of information in a function, and returning different results based on the calls to that function. Messy, jerry-rigged, but functional. I wouldn't recommend it for a BIG quiz game, but if you're going to use text files you're already being inefficient about it.
If you're planning on storing more than about 20 questions and answers I suggest you upgrade to a database.
function SwitchGroup(mainImage,largeFile,series)
{
document.getElementById(mainImage).src = largeFile;
document.getElementById(mainImage).rel = series;
var currdir = './glass/images/';
Anchor1 = document.getElementById('MainGallAnchorOne');
Anchor2 = document.getElementById('MainGallAnchorTwo');
Anchor3 = document.getElementById('MainGallAnchorThree');
Anchor4 = document.getElementById('MainGallAnchorFour');
Anchor5 = document.getElementById('MainGallAnchorFive');
Anchor6 = document.getElementById('MainGallAnchorSix');
if (series == 'series01')
{
// Messy, yes. But the data is all specific
Anchor1.href = currdir + 'series01/series0101big.jpg';
Anchor2.href = currdir + 'series01/series0102big.jpg';
Anchor3.href = currdir + 'series01/series0103big.jpg';
Anchor4.href = currdir + 'series01/series0104big.jpg';
Anchor5.href = currdir + 'series01/series0105big.jpg';
Anchor6.href = currdir + 'series01/series0106big.jpg';
Anchor1.title = 'Series 1';
Anchor2.title = 'Large Blue Bowl (m) (1)';
Anchor3.title = 'Blue Amphora (m)';
Anchor4.title = '14-16';
Anchor5.title = 'Aubergine Pitcher (m)';
Anchor6.title = 'Green and White and Twisty (m)';
Anchor1.rel = 'lightbox[series01]';
Anchor2.rel = 'lightbox[series01]';
Anchor3.rel = 'lightbox[series01]';
Anchor4.rel = 'lightbox[series01]';
Anchor5.rel = 'lightbox[series01]';
Anchor6.rel = 'lightbox[series01]';
}
if (series == 'series02')
{
Anchor1.href = currdir + 'series02/series0201big.jpg';
Anchor2.href = currdir + 'series02/series0202big.jpg';
Anchor3.href = currdir + 'series02/series0203big.jpg';
Anchor4.href = currdir + 'series02/series0204big.jpg';
Anchor5.href = currdir + 'series02/series0205big.jpg';
Anchor6.href = currdir + 'series02/series0206big.jpg';
Anchor1.title = 'Series 2 - Big Red and Orange Bowl (m)';
Anchor2.title = 'Crackled White and Black Bowl fading to Purple (m)';
Anchor3.title = 'Sparkly, Reduced, and odd (m)';
Anchor4.title = 'Spring Leaf (m)';
Anchor5.title = "My Sister's Christmas Present (m)";
Anchor6.title = 'Ornamental';
Anchor1.rel = 'lightbox[series02]';
Anchor2.rel = 'lightbox[series02]';
Anchor3.rel = 'lightbox[series02]';
Anchor4.rel = 'lightbox[series02]';
Anchor5.rel = 'lightbox[series02]';
Anchor6.rel = 'lightbox[series02]';
}
}

Categories

Resources