How to traverse an inner array in motoko? - motoko

I am new to Motoko and internet computer, when I am working I am having too much difficulties that might look simple, I am having difficulties doing this, posting the link to forum question here
https://forum.dfinity.org/t/how-to-traverse-inner-array-of-a-trie/12941?u=manubodhi
Please help if somebody is well versed in Motoko and Dfinity

I prepared a small code in motoko playground for you in order to see how you can traverse inner array and achieve your goal of filtering Trie. Here is as well saved project in motoko playground: https://m7sm4-2iaaa-aaaab-qabra-cai.raw.ic0.app/?tag=1150943578
Shortly to filter through inner array you can use:
let trieOfDishes = Trie.filter<DishId, Dish>(dishes, func (k, v) {
Array.find<MealTypeId>(v.mealTypeId, func(x : MealTypeId) { x == mealTypeId }) != null ;
});
Full code of canister implementation:
import Trie "mo:base/Trie";
import Array "mo:base/Array";
import Iter "mo:base/Iter";
import Nat32 "mo:base/Nat32";
actor Dishes {
type DishId = Nat32;
type DishTypeId = Nat32;
type MealTypeId = Nat32;
public type Dish = {
dishId: DishId;
dishTypeId : DishTypeId;
mealTypeId : [MealTypeId]
};
var dishes: Trie.Trie<DishId, Dish> = Trie.empty();
private func key(x : DishId) : Trie.Key<DishId> {
return { hash = x; key = x };
};
public func add_dish(dish: Dish) : async Dish {
dishes := Trie.replace(dishes, key(dish.dishId), Nat32.equal, ?dish).0;
return dish;
};
public query func getDishesByDishId (dishTypeId : DishTypeId) : async [(DishId, Dish)] {
let trieOfDishes = Trie.filter<DishId, Dish>(dishes, func (k, v) { v.dishId == dishTypeId } );
let arrayOfDishes : [(DishId, Dish)] = Iter.toArray(Trie.iter(trieOfDishes));
return arrayOfDishes;
};
public query func getDishesBymealTypeId (mealTypeId : MealTypeId) : async [(DishId, Dish)] {
let trieOfDishes = Trie.filter<DishId, Dish>(dishes, func (k, v) {
Array.find<MealTypeId>(v.mealTypeId, func(x : MealTypeId) { x == mealTypeId }) != null ;
});
let arrayOfDishes : [(DishId, Dish)] = Iter.toArray(Trie.iter(trieOfDishes));
return arrayOfDishes;
};
}

Related

How to get object of Maximum value from LiveData?

I have liveData of market data. I want one market data object which have highest 'volume'. Here, volume is string value("277927.5793846733451135"), it could be null also.
I am using below code to achieve this. but, its not working.
viewModel.marketlist.observe(this as LifecycleOwner, { marketdata ->
val marketData = marketdata.getOrNull()
if(marketData !=null) {
val mData: MarketData? = marketData.marketData?.maxByOrNull { checkNotNull(it.volume) }
if (mData != null) {
binding.textViewPrice.text = mData.price
}
}
else {
//TODO
}
})
Any help would be appreciated!
You should be able to do something like this:
viewModel.marketList.observe(viewLifecycleOwner) { marketData ->
val maxData = marketData.getOrNull()?.marketData?.let { dataValues ->
dataValues.maxByOrNull { it.volume?.toDoubleOrNull() ?: -1.0 }
}
if (maxData != null) {
binding.textViewPrice.text = maxData.price
}
}
I cleaned up the observe call a bit, then I'm checking if marketData.getOrNull().marketData is null right away with my let { ... } block.
If you do have marketData (the inner one), it'll then safely call maxByOrNull { it.volume }.

How to fold results from a few async calls

I want to get the results of my asynchronous function and use them in the fold function. Here's my function that didn't work:
private fun sendOrderStatus(list: List<OrderStatusEntity>) : Single<Boolean> {
return Single.just(
list.fold(true) { initial, item ->
if (!item.isTerminal()) {
val info = OrderStateParameters(
lon = item.orderStatusLon!!,
lat = item.orderStatusLat!!,
datetime = item.orderStatusDate!!
)
val state = OrderState(item.orderId, item.toSend(), info)
return tasksUseCase.sendOrderStatusForWorker(state)
.doOnSuccess { markSent(item) } // side calling
.flatMap {
return#flatMap initial && it.isSuccess // that result should be used in *fold*-function
}
} else // stub result
true
}
)
}
So, I intend to return a Single that will contain the aggregated result of all tasksUseCase.sendOrderStatusForWorker(state) calls.
Thank for any helps!

Turning BSPMapGen demo into a flxTilemap object

I'm trying to use the BSPMapGen demo to generate maps for my game but I'm having issues. The resulting map contains too many rooms and the hallways are twice as thick as they need to be. My guess was that the code uses the game dimensions somewhere but I couldn't find it.
screenshot
Here is the code (only has several changes from GenerateState):
package mapgen;
import flixel.tile.FlxTilemap;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flixel.util.FlxStringUtil;
import flixel.FlxG;
import flixel.util.FlxColor;
class BSPMap extends FlxTilemap
{
var TILE_SIZE:Int = 16;
public static var mapData:BitmapData;
var rooms:Array<Rectangle>;
var hallways:Array<Rectangle>;
var leafs:Array<Leaf>;
var mapWidth:Int;
var mapHeight:Int;
public function new(w:Int, h:Int, tilesize:Int)
{
super();
TILE_SIZE = tilesize;
mapWidth = w;
mapHeight = h;
generateMap();
var csvData:String = FlxStringUtil.bitmapToCSV(mapData);
this.loadMapFromCSV(csvData, "assets/tiles.png", TILE_SIZE, TILE_SIZE, AUTO);
}
function generateMap():Void
{
// Reset mapData
mapData = new BitmapData(mapWidth, mapHeight, false, FlxColor.BLACK);
// Reset arrays
rooms = [];
hallways = [];
leafs = [];
// First, create leaf to be root of all leaves
var root = new Leaf(0, 0, mapWidth, mapHeight);
leafs.push(root);
var didSplit:Bool = true;
// Loop through every Leaf in array until no more can be split
while (didSplit)
{
didSplit = false;
for (leaf in leafs)
{
if (leaf.leftChild == null && leaf.rightChild == null) // If not split
{
// If this leaf is too big, or 75% chance
if (leaf.width > Leaf.MAX_SIZE || leaf.height > Leaf.MAX_SIZE || FlxG.random.float() > 0.25)
{
if (leaf.split()) // split the leaf!
{
// If split worked, push child leafs into vector
leafs.push(leaf.leftChild);
leafs.push(leaf.rightChild);
didSplit = true;
}
}
}
}
}
// Next, iterate through each leaf and create room in each one
root.createRooms();
for (leaf in leafs)
{
// Then draw room and hallway (if there is one)
if (leaf.room != null)
{
drawRoom(leaf.room);
}
if (leaf.hallways != null && leaf.hallways.length > 0)
{
drawHalls(leaf.hallways);
}
}
//updateSprite();
}
function drawHalls(hallRect:Array<Rectangle>):Void
{
for (rect in hallRect)
{
hallways.push(rect);
mapData.fillRect(rect, FlxColor.WHITE);
}
}
/**
* Add this room to room array, then draw onto mapData
*/
function drawRoom(roomRect:Rectangle):Void
{
rooms.push(roomRect);
mapData.fillRect(roomRect, FlxColor.WHITE);
}
}

Pass by value. Array

I have two arrays. But when I change second - first change too.
I tried
.clone()
.copyOf()
but it didn't work for me.
object MatrixObject {
var table: Array<Array<Int>>? = null
fun randOf(n: Int) {
table= Array(n, { Array(n, { Random().nextInt(100 - 0) + 0 }) })
}
var tableF: Array<Array<Int>>? = null
get() {
if (field==null)
factorization()
return field
}
fun factorization() {
tableF = table!!
... //here I change elements of tableF
}
}
I tried
for(row in 0 until table!!.size)
tableF!![row] = Arrays.copyOf(table!![row], table!![row].size)
and
for(row in 0 until table!!.size)
tableF!![row] = table!![row].clone() // and copyOf()
but it still doesn't work.
I found the solution.I initialized the array.
tableF= Array(table!!.size, { Array(table!!.size, {0}) })
for(row in 0 until table!!.size)
tableF!![row] = table!![row].clone()

Squeryl partial update does not compile

I'm not sure what squeryl is trying to tell me here:
Error: Cannot prove that org.squeryl.dsl.fsm.Unconditioned =:= org.squeryl.dsl.fsm.Conditioned.
On:
inTransaction {
update(AppDB.postTable) { p =>
where(p.id === postId)
set(p.upVotes := p.upVotes.~ + 1)
}
The error is on the set clause
schema:
object AppDB extends Schema {
val postTable = table[Post]("post")
val replyTable = table[Reply]("reply")
val postToReplies = oneToManyRelation(postTable, replyTable)
.via((p,r) => p.id === r.postId)
}
case class Post(body: String, image:Option[String]) extends KeyedEntity[Long] {
val id: Long = 0
val posted: Date = new Date()
var upVotes: Long = 0
var downVotes: Long = 0
}
case class Reply(postId: Long, body: String, image:Option[String]) extends KeyedEntity[Long] {
val id: Long = 0
val posted: Date = new Date()
}
Thanks for any help.
Try using () instead of {} around your where and set clauses, like:
inTransaction {
update(AppDB.postTable) ( p =>
where(p.id === postId)
set(p.upVotes := p.upVotes.~ + 1)
)
}
I am not sure why, but I have had issues with {} in the past. When I tested the change against your code, the problem seemed to get resolved.