Console.log for solidity Array of Structure - structure

I would like to use the console.log for displaying an array of structure. I succeed only in displaying an attribute of the structure, not the all structure.
I got this error: Member "log" not found or not visible after
argument-dependent lookup in type(library console)
My structure:
struct Track {
string title;
uint duration; }
struct Musician {
string name;
Track[] tracks; }
mapping(address => Musician) Musicians;
And my function to return my data:
function getAllMusicians() /*external*/ public view returns (Musician[] memory){
Musician[] memory musicianList = new Musician[](addressMusicianNumber);
for (uint i = 0; i < addressMusicianNumber; i++) {
musicianList[i] = Musicians[addressMusician[i]];
console.log("musicianList >> ", Musicians[addressMusician[i]].name); //OK
console.log(musicianList[i].name); //OK
console.log(musicianList[i].tracks[0].title); //OK
console.log(musicianList[i]); //NOK
}
//console.logBytes32("musicianList >> ", bytes(musicianList[0])); //NOK
//console.log("musicianList >> ", bytes(musicianList[0])); //NOK
//console.log("musicianList >> ", musicianList); //NOK
return musicianList;
//emit getMusicianList(musicianList);
}
How to get all the array of structure ? such as:
[
{
name:'musician1',
tracks:[
{title: 'name1', duration: 340},
{title: 'name2', duration: 30}
]
},{
name:'musician2',
tracks:[
{title: 'name3', duration: 34},
{title: 'name4', duration: 31}
]
}
]

My solution was to go into the debugger.

Related

It is corret usage to create a tab for mithril?

I want to create a simple Tab but I think it is strange for my using:
var root = document.body
var index = {
view: () => index.html,
html: m('div', { id: 'div1' }, [
[
(function () {
let value = ["A", "B", "C", "D"]
let output = []
for (let i = 0; i < 4; i++) {
output.push(m('input', {
class: (function () {
if (i == 0) return "onit"
})(),
type: 'button',
value: value[i],
onclick: function () {
let div1 = document.getElementById("div1")
let btn = div1.getElementsByTagName("input")
let div1_div = div1.getElementsByTagName("div")
let _this = this
let num = (function () {
for (let i = 0; i < btn.length; i++) {
if (btn[i] == _this) {
return i
}
}
})()
for (let i = 0; i < btn.length; i++) {
btn[i].className = ""
}
this.className = "onit"
for (let i = 0; i < div1_div.length; i++) {
div1_div[i].setAttribute("style", "dispaly:none")
}
div1_div[num].setAttribute("style", "display:block")
}
}))
}
return output
})()
],
[
(function () {
let arr = ["aaa", "bbb", "ccc", "ddd"]
let output = []
for (let i = 0; i < 4; i++) {
output.push(m("div", { style: (the => i == 0 ? "display:block" : undefined)() }, arr[i]))
}
return output
})()
]
])
}
m.route(root, "/index", {
"/index": index
})
Is there any other simple way to achieve this?
If I click the button, the style of button will change and the display of all "div" will be changed. Screenshot
In mithril.js views you can only use expressions, for-loops, ifs and so on are no expressions and only possible the way you did it. Nevertheless there are other ways to achieve this
Loops can be achieved using the functional counterparts
let values = ["A", "B", "C", "D"]
let output = []
function(){
for (let i = 0; i < 4; i++) {
output.push(m('span', value)
}
return output
}()
can be written as
values.map(value => m('span', value)
if-Statements can be written using the ternary expression
function() {
if (condition) {
return 'this'
} else {
return 'that'
}
}()
just use
condition ? 'this' : 'that'
You can also use view functions if your view code gets to deeply nested and you need custom logic:
function someOtherView(someData) {
if (someData.shouldBeShown) {
return someData.text
}
}
function someView() {
...
someOtherView(someData)
...
}
This also makes your views more readable.

using vue.set in vuex is not updating the state

I'm trying to add an object into a nested array, and it is not working, but I've used this for other states and it works fine.
Has it got something to do with it begin a nested array?
this is the code I'm using
Vue.set(state.sections[getCurrentSection(state).index].rows[getCurrentRow(state).index].columns[getCurrentColumn(state).index].elements, 0, element)
this is the element object
var element = {
id: id,
style: {
backgroundColor: {
value: 'rgba(255,255,255,1)',
},
},
}
what am I doing wrong?
UPDATE
Another option to clone:
function hasProp(arg1, arg2) {
return Object.prototype.hasOwnProperty.call(arg1, arg2);
}
function extend(arg1, arg2) {
const keys = Object.keys(arg2);
const len = keys.length;
let i = 0;
while (i < len) {
arg1[keys[i]] = arg2[keys[i]];
i += 1;
}
if (hasProp(arg2, 'toString')) {
arg1.toString = arg2.toString;
}
if (hasProp(arg2, 'valueOf')) {
arg1.valueOf = arg2.valueOf;
}
return arg1;
}
const obj1 = {
a: 1,
b: 2,
c: { a: 1, b: 2}
};
const cloned = extend({}, obj1);
cloned.a = 9999;
console.log(obj1, cloned);
Make a deep copy of your state.sections;
Create a new object and make your modifications on it;
Replace state.sections with you new object - state.sections = Object.assign({}, newObject).
Your state and your view updated.

Realm very slow for adding/updating records

I have this react native application which imports the phone contacts to database. I have about 100 contacts in my phone and it's taking ages...like 1 import per second which is. I'm sure, a mistake I'm doing somewhere even though the code is simple.
realm.write(() => {
for (let i = 0, len = contacts.length; i < len; i++) {
Contact.saveOrUpdate(contacts[i].name, contacts[i].recordID, contacts[i].phoneNumbers);
}
});
saveOrUpdate method:
class Contact {
static saveOrUpdate(name, recordId, phones) {
const save = () => {
let c;
try {
// try an update first
c = realm.create('Contact', {
name: name.toString(),
recordID: recordId.toString()
}, true);
} catch (e) {
// if that fails, create a new contact
console.log("Created " + recordId);
c = realm.create('Contact', {
name: name.toString(),
recordID: recordId.toString()
});
}
c.phones = [];
for (let i = 0, len = phones.length; i < len; i++) {
c.phones.push({
number: phones[i].toString()
});
}
// now run an update with the phone numbers
return realm.create('Contact', c, true);
};
return save();
}
}
My realm schema:
const PhoneNumberSchema = {
name: 'PhoneNumber',
properties: {
number: 'string'
}
};
const ContactSchema = {
name: 'Contact',
primaryKey: 'recordID',
properties: {
recordID: 'string',
name: {
type: 'string',
indexed: true
},
phones: {
type: 'list',
objectType: 'PhoneNumber'
}
}
};
Can anyone spot what am I doing wrong here that it takes so long for 100 contacts to be stored?

Pushing to list in realm

These are my realm objects. I have Hole and Round. I am trying to populate my round with 18 hole objects in a single write but I've been stuck on this for the past few hours and I can't seem to understand where I'm going wrong.
class Hole extends Realm.Object {}
Hole.schema = {
name: 'Hole',
primaryKey: 'id',
properties: {
id: 'int',
fullStroke: 'int',
halfStroke: 'int',
puts: 'int',
firstPutDistance: 'int',
penalties: 'int',
fairway: 'string'
},
};
class Round extends Realm.Object {}
Round.schema = {
name: 'Round',
primaryKey: 'id',
properties: {
id: 'string',
done: 'string',
holes: {type: 'list', objectType: 'Hole'}
},
};
Here is my function that is attempting to push every hole into the hole property of Round. Any help would be greatly appreciated.
exportRound = () => {
let holesObjects = realm.objects('Hole')
if(holesObjects.length < 9){
alert('Enter stats for at least 9 holes please')
}
else{
var sortedHoles = holesObjects.sorted('id')
currentRound = realm.objects('Round').filtered('done == "no"')
for(var i = 1; i < holesObjects.length; i++){
console.log(holesObjects.filtered('id == i'))
realm.write(()=> currentRound.holes.push(holesObjects.filtered('id == {i}')) )
}
}
}
What's error are you facing?
I found some mistake in your code.
The type of currentRound object is Results. It is not Round object until you retrieve each element. So it doesn't have holes property. You should retrieve the element contained by Results, like the following:
var currentRound = realm.objects('Round').filtered('done == "no"')[0]
String interpolation should be `id == ${i}` (Use backtick and ${}). So your query should be:
holesObjects.filtered(`id == ${i}`)
holesObjects.filtered(`id == ${i}`) returns also Results object. You should retrieve an element first.
realm.write(()=> currentRound.holes.push(holesObjects.filtered(`id == ${i}`)[0]))
The whole code that I edited is the following:
exportRound = () => {
let holesObjects = realm.objects('Hole')
console.log(holesObjects);
if(holesObjects.length < 9){
alert('Enter stats for at least 9 holes please')
}
else{
var sortedHoles = holesObjects.sorted('id')
var currentRound = realm.objects('Round').filtered('done == "no"')[0]
console.log(currentRound)
for(var i = 1; i < holesObjects.length; i++){
console.log(holesObjects.filtered(`id == ${i}`))
realm.write(()=> currentRound.holes.push(holesObjects.filtered(`id == ${i}`)[0]))
}
}
}

Pivot data dynamically for google line chart

I want to display "population" of various countries through the years in the same line chart. The data displayed is based on selections from a multi-select dropdown "Countries". Underlying Data Table has 3 columns:
Year, Country, Population
2012,countryA,33
2013,countryA,35
2014,countryA,40
2012,countryB,65
2013,countryB,70
2014,countryB,75
2012,countryC,15
2013,countryC,20
2014,countryC,25
I am trying to create a pivoted Data View from the underlying Data Table
The code I am using is:
function drawLineChart() {
var arr = $('#country').val();
var lineChartJson = $.ajax({
url: "../json/lineChart.json",
dataType: "json",
async: false
}).responseText;
var lineChartData = new google.visualization.DataTable(lineChartJson);
var view = new google.visualization.DataView(lineChartData);
var viewCols = [0];
for(var i = 0; i < arr.length; i++) {
var viewCols1 = [{
type: 'number',
label: arr[i],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[i]) ? dt.getValue(row, 2) : null;
}
}];
viewCols = viewCols.concat(viewCols1);
}
view.setColumns(viewCols);
var aggCols = [{
column: 1,
type: 'number',
label: view.getColumnLabel(1),
aggregation: google.visualization.data.sum
}];
for(var i = 2; i < 4; i++) {
var aggCols1 = [{
column: i,
type: 'number',
label: view.getColumnLabel(i),
aggregation: google.visualization.data.sum
}];
aggCols = aggCols.concat(aggCols1);
}
var pivotedData = google.visualization.data.group(view, [0], aggCols);
But this does not seem to work as expected and I just get 1 Line in the chart with values for all countries added up (although I can see the legend for 3 countries)
On the other hand if I set my View columns as below, it works as expected.
view.setColumns([0, {
type: 'number',
label: arr[0],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[0]) ? dt.getValue(row, 2) : null;
}
}, {
type: 'number',
label: arr[1],
calc: function (dt, row) {
// return values of C only for the rows where B = "bar"
return (dt.getValue(row, 1) == arr[1]) ? dt.getValue(row, 2) : null;
}
}, {
type: 'number',
label: arr[2],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[2]) ? dt.getValue(row, 2) : null;
}
}]);
What is going wrong in the loop? Is something wrong with "concat" in the loop where I am creating View Columns? I also saw the viewCols array by using console.log and it seems to have the right elements
I was trying to follow the below post:
Creating pivoted DataView from existing google charts DataTable object
the problem has to do with scope
arr[i] is undefined within calc: function (dt, row)
here is another way to pivot the data...
google.charts.load('current', {
callback: function () {
var arr = [
'countryA',
'countryB',
'countryC'
];
var lineChartData = google.visualization.arrayToDataTable([
['Year', 'Country', 'Population'],
[2012,'countryA',33],
[2013,'countryA',35],
[2014,'countryA',40],
[2012,'countryB',65],
[2013,'countryB',70],
[2014,'countryB',75],
[2012,'countryC',15],
[2013,'countryC',20],
[2014,'countryC',25]
]);
// sort by year
lineChartData.sort([{column: 0}]);
// get unique countries
var countryGroup = google.visualization.data.group(
lineChartData,
[1]
);
// build country data table
var countryData = new google.visualization.DataTable({
cols: [
{label: 'Year', type: 'number'},
]
});
// add column for each country
for (var i = 0; i < countryGroup.getNumberOfRows(); i++) {
countryData.addColumn(
{label: countryGroup.getValue(i, 0), type: 'number'}
);
}
// add row for each year / country
var rowYear;
var rowIndex;
for (var i = 0; i < lineChartData.getNumberOfRows(); i++) {
if (rowYear !== lineChartData.getValue(i, 0)) {
rowYear = lineChartData.getValue(i, 0);
rowIndex = countryData.addRow();
countryData.setValue(rowIndex, 0, rowYear);
}
for (var x = 1; x < countryData.getNumberOfColumns(); x++) {
if (countryData.getColumnLabel(x) === lineChartData.getValue(i, 1)) {
countryData.setValue(rowIndex, x, lineChartData.getValue(i, 2));
}
}
}
// draw agg table
new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'table-div',
dataTable: countryData
}).draw();
// draw line chart
new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart-div',
dataTable: countryData
}).draw();
},
packages: ['corechart', 'table']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="table-div"></div>
<div id="chart-div"></div>
I could figure out the problem with my code above.
"calc" is the callback function in loop. So only last value of loop variable "i" is visible within the loop.
Putting a wrapper function fixes it:
for(var i = 0; i <= arr.length; i++)(function(i) {
var viewCols1 = [{
type: 'number',
label: arr[i],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[i]) ? dt.getValue(row, 2) : null;
}
}];
viewCols = viewCols.concat(viewCols1);
})(i);