Passing nested tables from Lua to C - c++

I have the following nested table defined in Lua. I need to pass it into my C++ program so that I can accurately read it's values. I know I can pass a single table to Lua using the
lua_getglobal(L, "parameters")
function. But in this case since it is nested, how can I deal with it?
parameters =
{
fuel = 100,
damage = 250,
maxspeed = 250,
levels =
{
{
fuel = 200,
damage = 600,
maxspeed = 300,
},
{
fuel = 300,
damage = 750,
maxspeed = 400,
},
}
}

The lua_getglobal will work for "parameters" just like any other variable. You will receive the table on the top of the stack. Once there, you can use the lua_gettable(), lua_getfield() and lua_rawget*() functions to access its fields. The fact that the table is nested makes no difference in accessing it at all. To access a subtable, push it onto the stack with those functions and access it in the same way as its "parent" table.

Related

How can I scale my dataset values as a percentage of the index in chart.js?

Sorry if the question is poorly worded.Here is my chart
I am looking into scaling the chart's display of dataset(s) values as a percentage such as:
//input
data:{
datasets[{
label: 'data1',
data: [15, 22, 18, 35, 16, 29, 40]
},
{
label: 'data2',
data: [20, 21, 20, 19, 21, 22, 35]
}]
data1's points on the chart would be displayed as [42.9, 51.2, 47.4, 64.8, 43.2, 56.9, 57.1]
data2's points on the chart would be displayed as [57.1, 48.8, 52.6, 35.2, 56.8, 43.1, 42.9]
It should look like this. All visible lines should stack up to 100%. If a dataset is hidden, how can I recalculate the percentage and update the chart so that everything stays stacked up to 100%?
I thought about doing a plugin where I do the calculation using myLine.data.datasets but then I don't know how to remove a hidden dataset's values from the calculation and I'm not sure how to display it unless I overwrite the original datasets. I'm pretty sure this is the wrong approach.
Any help would be greatly appreciated.
So, I figured it out. I needed to write a function to calculate the percentage area of the points in the index and then update the datasets with the calculated percentage values.
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
* DS_update calculates the percentage area of the input datasets
*
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
function DS_update(dataset_in, ds_vis){
// make a deep copy (no references to the source)
var temp = jQuery.extend(true, [], dataset_in);
// gets the sum of all datasets at a given index
function getTotal(index){
total = 0;
// step through the datasets
dataset_in.forEach(function(e, i){
// inc total if the dataset is visible
if(ds_vis[i]){
total += e[index];
}
// do nothing if the dataset is hidden
});
return total;
}
// update temp array with calculated percentage values
temp.forEach(function(el, ind){
var j = ind;
el.forEach(function(e, i){
// calculate percentage to the hundredths place
temp[j][i] = Math.round((e / getTotal(i))*10000)/100;
});
});
return temp;
}
Once I tested the functions I had to run them before initial load of the chart or else the user would see the datasets as non area-percent (raw data). which looks something like this:
// Keep source array to use in the tool tips
var Src_ary = Input_data; // multidimensional array of input data
// holds the percent-area calculations as datapoints
var Prod_ary = DS_update(Src_ary, Init_visible(Src_ary));
Next up was updating the onClick for the legend. I need this to update the calculations every time an item's visibility is toggled:
legend: {
position: 'bottom',
usePointStyle: true,
onClick:
function(e, legendItem){
var index = legendItem.datasetIndex;
var ci = this.chart;
var meta = ci.getDatasetMeta(index);
var vis_ary = [];
var updatedSet = [];
// See controller.isDatasetVisible comment
meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
// load the visible array
for(var i = 0; i < (ci.data.datasets || []).length; i++){
switch (ci.getDatasetMeta(i).hidden){
case null:
vis_ary.push(true);
break;
default:
vis_ary.push(false);
break;
}
}
// update datasets using vis_ary to tell us which sets are visible
updatedSet = DS_update(Prod_ary, vis_ary);
myLine.data.datasets.forEach(function (e,i){
e.data = updatedSet[i];
});
// We did stuff ... rerender the chart
ci.update();
}
}
END RESULT
This is what I was trying to do: highchart fiddle
This is what I ended up with:fiddle
It took a few days and a lot of reading through chartjs.org's documentation to put this together. In the end I think it came out pretty good considering I am new to chart.js and borderline illiterate with javascript.

Xamarin Forms - Get the size of an AbsoluteLayout

I cannot find the way to get the Width and the Height of a Xamarin.Forms.View.
I have this object:
public class SquareLayout : View
{
public static readonly BindableProperty ScalingBaseProperty =
BindableProperty.Create(nameof(ScalingBase), typeof(ScalingBaseType), typeof(SquareLayout), ScalingBaseType.Average,
propertyChanged: OnScalingBasePropertyChanged);
public ScalingBaseType ScalingBase
{
get { return (ScalingBaseType)GetValue(ScalingBaseProperty); }
set { SetValue(ScalingBaseProperty, value); }
}
public enum ScalingBaseType
{
Average,
Height,
Width
}
public static void OnScalingBasePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
SquareLayout sq = ((SquareLayout)bindable);
Debug.WriteLine("|Width = {0}|Height = {1}|", sq.Bounds.Width, sq.Bounds.Height);
switch (sq.ScalingBase)
{
case ScalingBaseType.Average:
double size = (sq.Bounds.Width + sq.Bounds.Height) / 2;
sq.WidthRequest = size;
sq.HeightRequest = size;
break;
case ScalingBaseType.Height:
sq.WidthRequest = sq.Bounds.Height;
break;
case ScalingBaseType.Width:
sq.HeightRequest = sq.Bounds.Width;
break;
}
Debug.WriteLine("|Width = {0}|Height = {1}|", sq.Bounds.Width, sq.Bounds.Height);
}
}
Basically, you declare somewhere this SquareLayout and then, based on an Enum, the layout is resized as a Square.
So, I then have this XAML part
<ContentPage.Content>
<AbsoluteLayout BackgroundColor="White">
...
<AbsoluteLayout x:Name="ToolsLayout" BackgroundColor="Red"
AbsoluteLayout.LayoutBounds="0.5, 0.05, 0.9, 0.075"
AbsoluteLayout.LayoutFlags="All">
<control:SquareLayout BackgroundColor="White" ScalingBase="Height"
AbsoluteLayout.LayoutBounds="0, 0.5, 0.1, 1"
AbsoluteLayout.LayoutFlags="All">
</control:SquareLayout>
<control:SquareLayout BackgroundColor="White" ScalingBase="Height"
AbsoluteLayout.LayoutBounds="1, 0.5, 0.1, 1"
AbsoluteLayout.LayoutFlags="All">
</control:SquareLayout>
</AbsoluteLayout>
...
</AbsoluteLayout>
</ContentPage.Content>
Which would give me a Rectangle with two Square around.. But nothing !
I tried to display the Width and the Height but nothing.. I tried the Bounds as well as you can see in the example, but nothing one more time..
The only values I get are -1
Does someone can help me? Thank in advance !
Xamarin has very less documentation for newbies , took some time to figure this out , basically during design time the the width and height property have a default value of -1 , which indicates auto , there is no way of knowing during design time what the values will be , hence you need to use 'events' to get the width and height property in this case you will use SizeChanged event , when the layout bounds are set during runtime this event will trigger.
In your xaml codebehind use this event to get your widh and height of yourlayout , i have used a lambda function , this can be implemented in many ways i just find this method easy.
yourlayout.SizeChanged+=(sender,e)=>
{
//Add your child objects here and set its values using yourlayout.Height etc
};
Instead of adding your children within this function you can use it to return a value and use that instead.
NOTE:I am not sure if this is the best practice for MVVM or otherwise

Trouble creating pointer to abstract class

I coded some smiley faces into my app recently, but I'm having trouble calling it in my option interface. The reason I'm wanting to call it from optioninterface is I want to add 2 sets of emojis, and if the value of Setting.nEmoji is 0 or 1 call a different set. The function loademojis() gets called when the application starts (it's technically coded in the interface solution). I can call it from a function that handles user input, but it generated horrible lag, I assume because each time a letter was typed, it cleared the array and loaded the emojis in again. So long story short, I was wondering if there's any way at all to create a pointer to a abstract class so I could call this from my option menu. Everytime I create a pointer and call it from theoption menu it crashes. Here's how I'm creating the pointer
MDrawContext* pDC
void MDrawContext::LoadEmojis()
{
if (Z_VIDEO_EMOJIS == 1)
{
m_Emoji[";)"] = "wink.png";
m_Emoji[":)"] = "smile.png";
m_Emoji[":D"] = "biggrin.png";
m_Emoji[":("] = "frown.png";
m_Emoji[":O"] = "eek.png";
m_Emoji[":P"] = "tongue.png";
m_Emoji[":?"] = "confused.png";
m_Emoji[":4"] = "cool.png";
m_Emoji[":3"] = "redface.png";
m_Emoji[":#"] = "mad.png";
m_Emoji[":I"] = "rolleyes.png";
m_Emoji[":K"] = "kappa.png";
}
else
{
m_Emoji[";)"] = "wink2.png";
m_Emoji[":)"] = "smile2.png";
m_Emoji[":D"] = "biggrin2.png";
m_Emoji[":("] = "frown2.png";
m_Emoji[":O"] = "eek2.png";
m_Emoji[":P"] = "tongue2.png";
}
}
//custom: reloademojis allows players to choose between ios/forum emojis
void MDrawContext::ReloadEmojis()
{
m_Emoji[";)"].clear();
m_Emoji[":)"].clear();
m_Emoji[":D"].clear();
m_Emoji[":("].clear();
m_Emoji[":O"].clear();
m_Emoji[":P"].clear();
m_Emoji[":?"].clear();
m_Emoji[":4"].clear();
m_Emoji[":3"].clear();
m_Emoji[":#"].clear();
m_Emoji[":I"].clear();
m_Emoji[":K"].clear();
LoadEmojis();
}
//Calling the pointer (different cpp)
int nEmojiType = 0;
if(nEmojiType != Z_VIDEO_EMOJI)
{
pDC->ReloadEmojis();
nEmojiType = Z_VIDEO_EMOJI;
}

C++ ListView hide item

I have created pretty much standard ListView.
RECT rec;
GetClientRect(hwnd, &rec);
ListView = CreateWindow(WC_LISTVIEW, (LPCSTR)L"", (WS_CHILD | WS_VISIBLE | LVS_REPORT), 0, 0, rec.right, rec.bottom-23, hwnd, (HMENU)8553, GetModuleHandle(NULL), NULL);
SendMessage(ListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); // Set style
Now I insert few columns like that:
LVCOLUMNW listColumnW = { 0 };
listColumnW.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
listColumnW.pszText = L"Column1";
listColumnW.cx = 150;
listColumnW.fmt = LVCFMT_LEFT;
SendMessage(ListView,LVM_INSERTCOLUMNW, 0, (LPARAM)&listColumnW);
after that I instert items and subitems
LVITEMW lisW = { 0 };
lisW.mask = LVIF_TEXT | LVIF_PARAM;
lisW.pszText = item_text[i];
lisW.iItem = i;
lisW.lParam = i;
SendMessage(ListView, LVM_INSERTITEMW, 0, (LPARAM)&lisW);
Now I'd like to implement some kind of search / filtering.
I see many people suggest to delete/reinsert items, however as there are quite a number of items in my listview that isn't the best solution.
While googling I learned that it should be possible to set groupid and set state of item (hide it).
However I'm not sure exactly how to do that, lets say I have 10 items in my listview and I want to hide some items, how exactly do I do that?
EDIT:
I have set LVM_ENABLEGROUPVIEW and created two groups, one is supposed to be shown and other one hidden.
LVGROUP group = { 0 };
group.cbSize = sizeof(LVGROUP);
group.mask = LVGF_GROUPID;
group.iGroupId = 10;//shown
ListView_InsertGroup(ListView, -1, &group);
group.iGroupId = 11;//hidden
group.mask = LVGF_GROUPID | LVGF_STATE;
group.stateMask = LVGS_HIDDEN;
group.state = LVGS_HIDDEN;
ListView_InsertGroup(ListView, -1, &group);
Now I have added some items to both groups, only problem is I can see them both (they are separated), while the other one is supposed to be hidden.
Use LVM_SETITEM to assign a list item to a specific group via the LVITEM::iGroupId member:
LVITEMW lisW = { 0 };
lisW.mask = ... | LVIF_GROUPID;
...
lisW.iItem = ...;
lisW.iGroupId = ...;
SendMessage(ListView, 0, (LPARAM)&lisW);
You can use LVM_INSERTGROUP to insert a hidden group, or use LVM_SETGROUPINFO to hide an existing group, by setting its LVGROUP::state member to LVGS_HIDDEN:
LVGROUP grp = { 0 };
grp.cbSize = sizeof(grp);
grp.mask = LVGF_STATE;
grp.iGroupId = ...;
grp.stateMask = LVGS_HIDDEN | LVGS_NOHEADER | LVGS_COLLAPSED;
grp.state = LVGS_HIDDEN | LVGS_NOHEADER | LVGS_COLLAPSED;
SendMessage(ListView, LVM_INSERTGROUP, -1, (LPARAM)&grp);
or:
SendMessage(ListView, LVM_SETGROUPINFO, grp.iGroupId, (LPARAM)&grp);
Make sure you have enabled groups via LVM_ENABLEGROUPVIEW beforehand:
SendMessage(ListView, LVM_ENABLEGROUPVIEW, TRUE, 0);
That being said, when you have lots of items to display/search/filter in a ListView, you are usually better off using the ListView in virtual mode instead. You can pre-filter your data as needed, then use LVM_SETITEMCOUNT to specify the number of items you want to display, and then handle LVN_GETDISPINFO to retrieve data for specific items when the ListView requests them from you. This way, you can do all of your searching/filtering within your datasource directly (in memory, in a database, etc), then simply invalidate the portions of the ListView that need to be refreshed onscreen using LVM_REDRAWITEMS when you have new data to display. When you have items to add/remove, you simply re-send LVM_SETITEMCOUNT. This is a much faster and flexible way to handle lots of list items.
Using virtual lists

Using Dojo Grid with REST (tastypie)

I am experimenting with Dojo, using a DataGrid/JsonRestStore against a REST-service implemented using Django/tastypie.
It seems that the JsonRestStore expects the data to arrive as a pure array, whilst tastypie returns the dataset within a structure containing "schema" and "objects".
{
"meta": {"limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1},
"objects": [{...}]
}
So, what I need is to somehow attach to the "objects" part.
What is the most sensible way to achieve this ?
Oyvind
Untested, but you might try creating a custom store that inherits from JsonRestStore and override the internal _processResults method. It's a two-liner in the Dojo 1.7 code base, so you can implement you own behavior quite simply.
_processResults: function(results, deferred){
var count = results.objects.length;
return {totalCount: deferred.fullLength || (deferred.request.count == count ? (deferred.request.start || 0) + count * 2 : count), items: results.objects};
}
See lines 414-417 of the dojox/data/JsonRestStore.js for reference.
I don't know whether this will helpful for you or not. http://jayapal-d.blogspot.in/2009/08/dojo-datagrid-with-editable-cells-in.html