Wednesday, February 24, 2021

pydroid

A small update has been released for PYDroid bringing it to 22.6.1.

The only API change in this release is hopefully minor - it changes setState functions to allow for the stateChange lambda to be a suspending function. For Kotlin users there should be basically zero code change. For Java users, this will change the function signature because in Java suspending functions are implemented as Continuation resume callbacks. While this change may be slightly more painful for Java, as Android continues moving to a Kotlin first ecosystem modern codebases must be ready to follow. PYDroid is Kotlin first and Java friendly, but I cannot make Java compatibility guarantees as I largely do not use Java anymore.

If the change to suspending state change callbacks causes issues, please file a bug report and let me know.

Stay tuned! 

Saturday, February 20, 2021

Quick updates

A quick patch release was pushed for FridgeFriend that brings it to version 32. This fixes a bad buggy in the Group detail screen where the list of Items would normally be present. A bug was causing this list to be blank until at least one letter was inputted into the Search box - the recent update will fix this issue. Please update as soon as possible to get the latest fix!

An update to the Discord stock bot was released that brings very basic support for the nearest weekly options that are close to or in the money. Unfortunately, the options info is still incomplete, as I would like it to at least be able to list monthly or leap options, as well as provide delta info. I will continue working on this to make it more complete, but basic support is there for now.

An update to bubblewrap-wrap has been pushed which brings better isolation for user-specific runtime directories.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Monday, February 15, 2021

new stuff

Some quick updates

My nameless discord stock bot has gained basic support for displaying the upcoming weekly options chain for a given symbol.

ZapTorch has been updated with support for toggling on and off the various double click volume commands, so you can use some or all of the different volume commands.

FridgeFriend has been updated with simple bugfixes and a change to the search screen (although this one is sitting in Google review limbo)

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Monday, January 25, 2021

New FridgeFriend

A new version of FridgeFriend has been released which includes some major changes!

First is the removal of the Map screen. This screen was originally envisioned to let you mark store locations on your device so that FridgeFriend could notify you when you were close by via geofencing. It was intended to be a hands off operation, so you wouldn't need the app open and could be, for example, driving around in the car and the app would notify you as you passed by a store. Unfortunately, the Google API and Policy changes with the new Android version made this feature much less useful - as you had to have the app open for it to remind you about nearby stores - and with the change in how society functions due to the pandemic, most people are not out and about anymore (and if they are, they usually have decided in advance to go to the store already). As such, the feature rarely saw any use and was not very useful when it did, so it has been dropped. A side effect of this is that FridgeFriend now requires zero permissions.

Instead, a global search screen has been added. Now when searching on this page, Items from any Group will be returned to you, allowing for a higher level birds-eye view over all of the things in your fridge. This way, even if you have items spread out among multiple Groups, you will be able to manage them all here as if they were in one large "super group".

The update has been published and should be rolling out to your device soon!

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

New pydroid

PYDroid version 22.6.0 has been released.

This officially removes the old deprecated methods, like saved instance support on plain UiViewModels.
This is largely the same release as 22.5.4 just with deprecated methods formally removed, but there is one change that can impact your application's behavior.

The setState function used to take an optional parameter andThen which would run only when the state was actually changed. This behavior has been modified, and the andThen callback will now run after every setState operation, regardless if state actually changes or not.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Monday, January 18, 2021

More state less bugs

PYDroid 22.5.4 follows quickly on the heels of the last release and brings some changes and some fixes that are pretty important, if I do say so myself.

The first is the removal of the SwipeRefreshLayout.refreshing(Boolean) extension function. This function was originally created to work around a bug in the SwipeRefreshLayout library by posting to the setRefreshing function, but later versions of that library fixed the bug so the extension function is no longer needed.

Another important change is to the setState mechanism on ViewModel and StateModel classes. The setState function used to open its own CoroutineScope which could not be cancelled except by cancelling the entire scope. This API still exists but may become deprecated in the near future in favor of the new APIs, which are extensions with the same signature but on the CoroutineScope object. As this is only a bugfix release, the old functions will stick around for the future, but may be removed in the next minor release.

Please upgrade to 22.5.4 when possible.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Thursday, January 14, 2021

pydroid and state saving

PYDroid has received an update to version 22.5.0! Major changes include new support for the androidx.savedstate module in UiViewModels! This support is optional.

UiViewModel will be deprecating the doOnRestoreState and doOnSaveState hooks. In the future, the UiViewModel class will no longer support instance state saving. For ViewModels wishing to use and write instance state, the new UiSavedStateViewModel class should be used (long names - I know - what is this - Java?). The UiSavedStateViewModel class takes in it's constructor an additional UiSavedState parameter, which is a simple abstraction over the SavedStateHandle class from androidx. You can access the UiSavedState via the restoreSavedState, putSavedState and removeSavedState functions.

Currently the UiSavedStateViewModel class is seperated from the UiViewModel class, but once the saved state migration is complete in a future version, the saved state view model will extend from the normal view model as a base class. Consumer API will not change, but ABI compatibility will not be maintained once this happens.

To facilitate these new ViewModels, a new factory has been created, called SavedStateViewModelFactory. To create simple factories, the new inline functions createViewModelFactory and createSavedStateViewModelFactory can be used to create simple single-value factories so that your custom ViewModels can play nice with Android's ViewModelStore system.

Along with these changes, the UiBundleReader and UiBundleWriter interfaces have been deprecated. For library consumers, this change is largely unimportant - but one thing that will affect consumers is that the UiBundleReader methods have been reduced to just the get(String): T? method. All other methods in the future will be removed. UiView consumer code will be largely unchanged, as long as all reader access is changed to only use get(String): T?.

The UiRender interface has removed support for the distinct function as it did not make any sense in the given context, and has renamed the distinctBy function to mapChanged to better convey how that function is used. The asUiRender extension function has been changed from being an extension on Any to being an extension on UiViewState only, so that random objects cannot be turned into renderers unintentionally.

PYDroid ui has been updated to use these new systems and now lazily initializes all of it's components, which should reduce the start up time cost. An optimization has been made to coroutine scope creation which should avoid a large time penalty during debug mode builds. In the future, support will begin for using UiViews as composable building blocks, but this will not be at least until compose-ui enters an API beta with stability guarantees.

Finally, some functions are exposed to a Java consumer that were intended to be internal to the library only. These functions have since been moved into an Internals class. You should not use these functions as a PYDroid library consumer - if you do, there is no support and functions can be radically changed or removed without warning. Don't use anything labelled internal, if you are able to access it, it is a mistake.

The bintray official release will be going up later today, stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Wednesday, January 13, 2021

Monster Hunter and being Prepared

Monster Hunter is a series about being prepared. While not a series for everyone, for those who do enjoy it, it can be one of the single most addicting things they play. The game rewards a player being prepared for any number of situations. Let's explore briefly how being prepared is rewarded in the latest entry of the series, Monster Hunter: Rise.

Note: These are impressions gathered from playing the Switch demo of the game in a multiplayer context. I am a beginner, as you will soon figure out.

Monster Hunter is for the patient gamer. The game almost downright requires that you study and practice before going off on a hunt. Before you hunt, you have to pick a weapon class. Before you pick a weapon class, you need to know how each performs to see what you like and don't like.

Before you can hunt, you need to go into weapon training. You need to pick a weapon and start trying it out - and not just pressing random buttons either. Monster Hunter is a slow game. If you start an attack, you need to already know in your head how you plan to end your attack, and you need to know when you are committed to finishing an attack animation for large damage, and when you need to stop the attack and dodge. To be prepared to train, you need to first read the weapon combos and understand what the "goal" of a weapon combo is.

Take for example, the Charge Blade. The "goal" of this weapon in it's normal usage is to unleash a fully charged Amped Element Discharge attack. In order to do that, you'll need to build charge. In order to do that, you'll need to land the standard sword combo first, which is X, X, X, then follow it up with ZR so that you do not enter the slower Axe mode before you are prepared with charged Vials. But you need to also not push ZR too early, or you will bring up your shield and enter Guard, which is not what you want to do. Once you have charge, you need to store your charge by switching to Sword mode and pressing ZR + A, which will store one set of Vials. Rinse and repeat this until you have two charged sets of Vials, and then you can enter Axe mode and release a fully charged Amped Element Discharge attack.

But when should you release your big attack that you've taken so much time to build up? Not when the monster is moving around obviously. You need to first knock the monster down and make it so that it is stunned for long enough for you to get the fully charged attack off. In order to do that, you need to understand it's weak points and strike them repeatedly.

Now that you are prepared, and have on where to hit the monster and when to use your big attacks, you need to hunt the monster. You can't kill what you can't find.

So you have to prepare to fight by finding clues around the map that can help lead you to the monster. Droppings, skeletons and remains, tracks - all of these are clues that can help build an understanding of what monster you are looking at, and how to find it.

In order to prepare to track the monster, you need to also prepare properly for the excursion. Eating the right food, gathering the right equipment, heck, even being the right class can help you better prepare for the hour long quest ahead.

All of these things stem back to the core gameplay focus - being prepared. The game rewards you for being patient and planning out all you can about your encounters. By being so rehearsed, you will be able to keep up when the game suddenly changes your quest in the middle by throwing in a second monster or a bigger monster, or replacing your quest target with a different monster entirely.

And of course, you need to be prepared to play with other people. Monster Hunter is a lot more fun with friends.

Code someday, stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Monday, January 11, 2021

Exploring the strategy in Monopoly

This is inspired by a recent conversation I had with my girlfriend, which ended with her stating:

"Why do people like Monopoly so much. All you do is buy a house, what the fuck?"

In this post I wish to explore the sentiment expressed by this reductionist viewpoint to see if, in my own understanding, Monopoly is truly no deeper than rolling dice and buying property. As a slight spoiler before I begin - I believe the game is ultimately deeper than my girlfriend gives it credit for.

Using a standard board, there are a number of different properties on the board that are available for a player to purchase. The board is broken up into 4 sides, which I will call "legs" for reference. Each leg is broken up into a couple of different sections which bear the same colors, which I will call "color groups". Let's break down the spaces that are most valuable, and lay out some general tips for the best games.


The strategy in Monopoly revolves around, ultimately, one very simple question:

"How long will I have to wait to make money if I buy Boardwalk?"

Everything you do should be based around the odds of making the money you've spent back in the lowest number of dice-rolls possible. This also means that there is a method to how much you should build on properties, as well as which properties you should pay money for and which you should avoid.

Control Color Groups
You should always purchase property with the mindset of figuring out how many turns it will take before you have been refunded for your spend. To this end, you must seek to control entire color groups for the most payout. The only time you should find yourself holding a single property outside of a group is when you are strategically holding it to prevent another player from completing a group.

The railroads
The railroads are very valuable for a player to own, but the maximum benefit comes from owning all 4 of the railroads. This is because the rent for a railroad starts at $25 and doubles with each other owned railroad. Because there are various event opportunities in the game which move a player to a railroad directly, and there is one railroad on each leg of the board, the railroads are the most important spaces in the game. You should always look to own all 4 to get the highest payout, owning 1 or 2 is only good when strategically preventing another player from holding the set.

Optimal house count
The optimal number of houses to have is 3 houses on most color groups. The one generally accepted exception to this rule is in the case of the dark-purple color group which is the spaces immediately in front of GO, where it is more optimal to have a hotel. The reason 3 is the optimal number in most cases is due to the cost of a house as compared to the multiplying factor it brings. The first house is always a must, it usually jumps the rent 5x from the empty lot value - Virgina Avenue for example jumps from 12 to 60 dollars on a single house. From there, each additional house brings around 3x in value, so up to 3 houses is generally optimal. Past this point, 4 houses or a hotel cost significantly more without as large of a multiplying factor (to prevent the game from getting overly large rent values). A 4th house usually brings in only an additional $100 dollars, and a hotel usually only an additional $200, despite costing the same as the first three houses. Instead of spending money on the 4th house and the hotel, you should look towards expanding the number of properties you own instead.

Property Priority
The best properties in the game to own are on the third and fourth legs of the board - the orange section with St. James and friends, the red section with Kentucky and friends, and the yellow section with Marvin Gardens and friends. This is because, due to how the dice rolls work, a person is statistically most likely to land on the orange section of the board. Following the orange roll, they would next visit either red or yellow. Quickly capturing and building property here can help you get a commanding lead in the game.

Stopping Group Ownership
It is highly important that you opportunistically purchase properties outside of your currently owned color groups, so that you can avoid other players having total control over a color group.

Go to Jail
In the early game, getting into jail can mean you lose opportunity to purchase other property, so you should always immediately pay the fee to get out so you can roll to claim new property in the early game. Jail is your favorite place in the late game though, because jail is free to stay. You should always take the opportunity to go to jail, because it avoids you needing to move around the board and putting yourself at risk of paying a large amount of rent to another player. While you are in jail you still collect rent, so its a win win! Late game Monopoly strategy can be summarized as: "The best way to win Monopoly is to not play."

Be nice
People are creatures of emotion. While not always a guarantee, if you are nice to another player, they may be nice to you. You should always try to be nice to the other players so that when that critical property goes to auction you can convince them to not challenge you - or you can sweetly whisper away that critical single railroad that you need while you offer them a large sum of money for it. Being nice can often make other players put their guard down and deviate from the optimal strategy, which can in turn allow you to correct mistakes you may have made. Be nice!


---

These are just a small set of essentially robotic strategy that produces the most optimal result. The variety of the game comes from the fact that no situation will play out exactly as this ideal scenario has. People will refuse to give up properties, or give away properties to your opponents. You will find yourself rolling poorly and never claiming full color groups, or you will find that your statistically high property is never landed on. The game is ever changing because of the people involved, and you must always be willing to adapt to your situation at hand. Also, remember not to take things too seriously, don't get frustrated if other players don't seem to be following an optimal strategy. It is, after all, just a board game.

As we can clearly see, Monopoly is at is core much simpler than just buy a house - roll a dice - win a game. In a reductionist viewpoint yes, those are the core steps, but the actual behind the scenes brainwork that goes into deciding where to buy a house, and the slight social manipulation evolve the game into something far deeper. Monopoly may not ultimately be the deepest thought worthy board game out there, but it does at least possess more depth than simply rolling dice and buying houses.


And finally, let me end with this - this is not a conversion attempt. If you dislike Monopoly I am not attempting to change your opinion. Regardless of how I understand the game to be, any perceived depth does not ultimately change whether or not the game is fun to play. If you like it, you like it. If you don't you don't. No amount of strategy discussion will ever seek to change that. I hope that you can assess the game as something which objectively can have depth and strategy, even if subjectively it may not be entertaining.



Code stuff next time. Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Friday, January 8, 2021

libs and more

Cachify has been updated to version 0.0.20 to fix a pretty nasty bug related to memory cache storage. This change comes with some major API changes.

The CacheStorage<K, V> interface is now a CacheStorage<T>. A CacheStorage interface now handles just one piece of cached data instead of requiring support for multiple pieces of data.

The entry points at cachify and multiCachify now take a lazy list of CacheStorage implementations instead of requiring you to initialize the CacheStorage at the callsite. This is so that multiCachify implementations do not all accidentally attempt to write to the same cache storage. CacheStorage instances are now separated between Cachify instances. The MultiCachify key function is now suspending so that we can guarantee the mapped backend has only one writer at a time. There is also a strict guarantee that a list of CacheStorage instances will be written to before being read, to make sure that data in the cache is consistently represented. All of these backing storage guarantees are handled by a simple suspending Mutex.

PYDroid has been bumped to version 22.4.4 which brings built in support for the In-App Billing v3 library. The library has a new billing module which handles the heavy lifting, and a reference implementation is built into the PYDroid ui library, and automatically initialized for you when using the ActivityBase class. A default interactive UI is also implemented in the AppSettingsPreferenceFragment class, via a "Donate" list item. The list will be populated out of the box if your IAP items use an id scheme that looks like: <package-name>.iap_{one,three,five,ten}. Currently there is only support for donation style consumable IAPs.

An update has been pushed for FridgeFriend which brings support for moving Items between Groups. You can better organize the stuff in your fridge by breaking large groups of items up into smaller subgroups, and this moving option can better facilitate that.

ZapTorch has gained support for additional button gestures. Double tapping the Volume Up button will cause the flash light to slowly pulse, and pressing one Volume Down followed by a Volume Up will cause a quick strobe effect.

I will formally publish the updates to the store once testing has been completed, probably today or tomorrow.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================