How to separate large numbers with spaces kotlin - android-studio

I have a calculator app and I want it to show large numbers with spaces between them when users enter their input. Currently, they don't have spaces between them like this: 10000; 100000; 1000000. I want them to show like this: 10 000; 100 000; 1 000 000. The second one looks much neater.
Here is my code
class CalculatorActivity : AppCompatActivity() {
#Suppress("PrivatePropertyName")
private var DigitOnScreen = StringBuilder(12)
private var operation: Char = ' '
private var leftHandSide: Double = 0.0
private var rightHandSide: Double = 0.0
private lateinit var binding: ActivityCalculatorBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCalculatorBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.resultId.text = "0"
initializeButtons()
}
private fun initializeButtons() {
functionalButtons()
operationalButtons()
numericalButtons()
}
/**
* This function initializes all of our numerical buttons from
* [0 - 9]
*/
private fun numericalButtons() {
binding.oneBtn.setOnClickListener {
appendToDigitOnScreen("1")
}
binding.twoBtn.setOnClickListener {
appendToDigitOnScreen("2")
}
binding.threeBtn.setOnClickListener {
appendToDigitOnScreen("3")
}
binding.fourBtn.setOnClickListener {
appendToDigitOnScreen("4")
}
binding.fiveBtn.setOnClickListener {
appendToDigitOnScreen("5")
}
binding.sixBtn.setOnClickListener {
appendToDigitOnScreen("6")
}
binding.sevenBtn.setOnClickListener {
appendToDigitOnScreen("7")
}
binding.eightBtn.setOnClickListener {
appendToDigitOnScreen("8")
}
binding.nineBtn.setOnClickListener {
appendToDigitOnScreen("9")
}
binding.zeroBtn.setOnClickListener {
appendToDigitOnScreen("0")
}
binding.dotBtn.setOnClickListener {
appendToDigitOnScreen(".")
}
}
/**
* Insert the button been clicked onto the screen so user can see
* inputs for the button clicked
*/
private fun appendToDigitOnScreen(digit: String) {
// Add each digit to our string builder
DigitOnScreen.append(digit)
// display it on the screen of our mobile app
binding.resultId.text = DigitOnScreen.toString()
}
/**
* Initialize the operation keys in our calculator like the
* addition key, subtraction key and the likes
*/
private fun operationalButtons() {
binding.additionBtn.setOnClickListener {
selectOperation('A')
}
binding.subtractBtn.setOnClickListener {
selectOperation('S')
}
binding.divideBtn.setOnClickListener {
selectOperation('D')
}
binding.multipyBtn.setOnClickListener {
selectOperation('M')
}
}
/**
* Function to assign operational sign to our math calculations
*/
private fun selectOperation(c: Char) {
operation = c
leftHandSide = DigitOnScreen.toString().toDouble()
DigitOnScreen.clear()
binding.resultId.text = "0"
}
/**
* Handles functional operations in out application like
* clear button, backspace button and the clear everything button
*/
private fun functionalButtons() {
binding.clearEverythingBtn.setOnClickListener {
DigitOnScreen.clear()
binding.resultId.text = "0"
}
binding.clearBtn.setOnClickListener {
if (DigitOnScreen.isEmpty()) {
return#setOnClickListener
} else {
clearDigit()
}
}
binding.backspaceBtn.setOnClickListener {
if (DigitOnScreen.isEmpty()) {
return#setOnClickListener
} else {
clearDigit()
}
}
binding.equalBtn.setOnClickListener {
performMathOperation()
}
}
/**
* This function performs our Math Operation which is then showed on the screen.
*/
private fun performMathOperation() {
rightHandSide = DigitOnScreen.toString().toDouble()
when (operation) {
'A' -> {
val sum = OperationsHelper.add(leftHandSide, rightHandSide)
binding.resultId.text = sum.toString()
DigitOnScreen.clear()
DigitOnScreen.append(sum)
}
'S' -> {
val subtract = OperationsHelper.subtract(leftHandSide, rightHandSide)
binding.resultId.text = subtract.toString()
DigitOnScreen.clear()
DigitOnScreen.append(subtract)
}
'M' -> {
val multiply = OperationsHelper.multiply(leftHandSide, rightHandSide)
binding.resultId.text = multiply.toString()
DigitOnScreen.clear()
DigitOnScreen.append(multiply)
}
'D' -> {
val divide = OperationsHelper.divide(leftHandSide, rightHandSide)
binding.resultId.text = divide.toString()
DigitOnScreen.clear()
DigitOnScreen.append(divide)
}
}
}
/**
* This function remove the last digit on the screen.
*/
private fun clearDigit() {
val length = DigitOnScreen.length
DigitOnScreen.deleteCharAt(length - 1)
if (length <= 0) {
binding.resultId.text = "0"
}else{
binding.resultId.text = DigitOnScreen.toString()
}
}

you can solve it like this for example :
val x = "10000000"
val s:StringBuilder = java.lang.StringBuilder("")
x.mapIndexed{ index, c ->
if ((index+1)%3 ==0){
s.append(" ")
}
s.append(c)
}
println(s)
you need to store the value of all digts -> and every 3 digit make a space

Related

Load image from firestore collection into LazyColumn in jetpack compose

My app has a navigation bar and in one navBarItem I have two tabs, I want to read images and their caption I have stored in my firebase firestore collection into a LazyColumn in one of the tabs.
Here is how my DataException and GalleryRepo class looks like
data class DataOrException<T, E : Exception> (
var data: T? = null,
var e: E? = null
)
#Singleton
class GalleryRepo #Inject constructor(
private val queryImageData: Query
) {
fun getImagesFromFirestore(): DataOrException<List<PQImageGallery>, Exception> {
val dataOrException = DataOrException<List<PQImageGallery>, Exception>()
try {
dataOrException.data = queryImageData.get()
.result.map { document -> document.toObject(PQImageGallery::class.java) }
} catch (e: FirebaseFirestoreException) {
dataOrException.e = e
}
return dataOrException
}
}
My data class
data class PQImageGallery (
var imageUrl: String? =null,
var caption: String? = null
)
ViewModels...
#HiltViewModel
class PQViewModel #Inject constructor(
private val repository: GalleryRepo
): ViewModel() {
var loading = mutableStateOf(false)
val data: MutableState<DataOrException<List<PQImageGallery>, Exception>> = mutableStateOf(
DataOrException(
listOf(),
Exception("")
)
)
init {
getGalleryCollection()
}
private fun getGalleryCollection() {
viewModelScope.launch {
loading.value = true
data.value = repository.getImagesFromFirestore()
loading.value = false
}
}
}
#Module
#InstallIn(SingletonComponent::class)
object RemoteImageModel {
#Provides
#Singleton
fun loadImagesInCollection() = FirebaseFirestore.getInstance()
.collection(IMAGE_COLLECTION)
}
My GalleryCollection composable file
#Composable
fun GalleryCollection(dataOrException: DataOrException<List<PQImageGallery>, Exception>) {
val images = dataOrException.data
images?.let {
LazyColumn {
items(items = images) { product ->
GalleryCard(pqImageGallery = product)
}
}
}
val e = dataOrException.e
e?.let {
Text(
text = e.message!!,
modifier = Modifier.padding(16.dp)
)
}
}
#Composable
fun GalleryCard(
pqImageGallery: PQImageGallery,
) {
Card(...) {
Box(modifier = Modifier
.fillMaxSize()
) {
pqImageGallery.imageUrl?.let { imageUrl ->
CoilImage(
data = imageUrl,
....
)
}
pqImageGallery.caption?.let { caption ->
Text(
text = caption,
...
)
}
}
}
}
My navBarItem that contains the two tabs called Home
class Home : ComponentActivity() {
private val viewModel: PQViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HomeScreen(viewModel)
}
}
}
#Composable
fun HomeScreen(
viewModel: PQViewModel
) {
val dataOrException = viewModel.data.value
val navController = rememberNavController()
val currentBackStack by navController.currentBackStackEntryAsState()
val currentDestination = currentBackStack?.destination
val currentScreen =
HomeTabRowScreens.find { it.route == currentDestination?.route } ?: GalleryView
Scaffold(
topBar = {
HomeScreenTabRow(
allScreens = HomeTabRowScreens,
onTabSelected = { newScreen ->
navController
.navigateSingleTopTo(newScreen.route)
},
currentScreen = currentScreen,
)
}
) { innerPadding ->
NavHost(
navController = navController,
startDestination = GalleryView.route,
modifier = Modifier.padding(innerPadding)
) {
composable(route = GalleryView.route) {
// GalleryTabScreen()
GalleryCollection(dataOrException = dataOrException)
}
composable(route = VirtualTourView.route) {
VirtualTourScreen()
}
}
}
}
fun NavHostController.navigateSingleTopTo(route: String) =
this.navigate(route) {
popUpTo(
this#navigateSingleTopTo.graph.findStartDestination().id
) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
Finally calling the Home class in my main screen(MainActivity)
NavHost(
..
) {
composable(NAV_HOME) {
Home()
}
composable(..) { ...}
}
The issue is when I run the app the tabs in the Home navBar doesn't show at all talk of loading the images from the firestore collection.
Also, is there another way to instantiate a viewModel without having to create a class that extends ComponentActiviy?
If there's another way to achieve this kindly share.

Kotlin Edit Text as Integer

I want to make an app where you have to guess two numbers that eaquals a random number. But my app crash at the start because of java.lang.NumberFormatException: For input string: ""
val intNumber1 = etNumber1.text.toString().toInt() is the line that causes the crash. But I dont know what to do.
Here is my main activity:
//Buttons und Text initialisieren
private lateinit var btnCheck: Button
private lateinit var tvRndNumber: TextView
private lateinit var etNumber1: EditText
private lateinit var etNumber2: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Buttons und Text verknüpfen
btnCheck = findViewById(R.id.checkButton)
tvRndNumber = findViewById(R.id.randomNumber)
etNumber1 = findViewById(R.id.inputNumber1)
etNumber2 = findViewById(R.id.inputNumber2)
val intNumber1 = etNumber1.text.toString().toInt()
val intNumber2 = etNumber2.text.toString().toInt()
fun getRandomNumber(): Int {
return Random.nextInt(0,100)
}
var intRdnNumber = getRandomNumber()
tvRndNumber.text = intRdnNumber.toString()
fun checkNumbers(num1: Int, num2: Int){
if (num1 + num2 == intRdnNumber) {
tvRndNumber.text = "Richtig"
}
else {
Toast.makeText(this,"Probier es nochmal", Toast.LENGTH_LONG).show()
}
}
btnCheck.setOnClickListener {
checkNumbers(intNumber1, intNumber2)
}
Try like the following
//....
val intNumber1 = etNumber1.text.toString()
val intNumber2 = etNumber2.text.toString()
//.....
btnCheck.setOnClickListener {
if(intNumber1.isNotEmpty && intNumber2.isNotEmpty{
checkNumbers(intNumber1.toInt(), intNumber2.toInt())
}else{
// input filed is empty
// show message or do nothing
}
}
val intNumber1 = if(etNumber1.text.isNotEmpty()) {
etNumber1.text.toString().toInt()
} else {
0
}
val intNumber2 = if(etNumber2.text.isNotEmpty()) {
etNumber2.text.toString().toInt()
} else {
0
}

How to handle 3 states of bottom sheet (expanded, half_expanded and collapsed) by sliding in Android Studio?

I need to handle 3 states of bottom sheet view by sliding up and down. For example, if current state is equals to STATE_EXPANDED then if I swipe down the state should be changed to STATE_HALF_EXPANDED and if swipe down again - STATE_COLLAPSED.
This is the code i have (i tried to work with slideOffset, but unsuccessfully):
BottomSheetBehavior.from(view.findViewById<LinearLayout>(R.id.bottom_sheet)).apply {
peekHeight = Resources.getSystem().displayMetrics.heightPixels / 2
this.state = BottomSheetBehavior.STATE_COLLAPSED
this.addBottomSheetCallback(object :
BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
if(slideOffset <= 0.7) {
if(prevOffset - slideOffset > 0) {
BottomSheetBehavior.from(bottomSheet).state = BottomSheetBehavior.STATE_COLLAPSED
}
else {
BottomSheetBehavior.from(bottomSheet).state = BottomSheetBehavior.STATE_HALF_EXPANDED
}
}
else {
if(prevOffset - slideOffset > 0) {
BottomSheetBehavior.from(bottomSheet).state = BottomSheetBehavior.STATE_HALF_EXPANDED
}
else {
BottomSheetBehavior.from(bottomSheet).state = BottomSheetBehavior.STATE_EXPANDED
}
}
prevOffset = slideOffset
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
when(newState) {
BottomSheetBehavior.STATE_EXPANDED -> peekHeight = Resources.getSystem().displayMetrics.heightPixels
BottomSheetBehavior.STATE_HALF_EXPANDED -> peekHeight = (Resources.getSystem().displayMetrics.heightPixels * 0.7).toInt()
BottomSheetBehavior.STATE_COLLAPSED -> peekHeight = Resources.getSystem().displayMetrics.heightPixels / 2
}
}
})
}

How do I keep the string value the same when the indicator buffer no longer gives a value?

I've coded a basic Expert Advisor to trigger a trade when the parameters are true. However, in this case the code will never meet all the requirements because the string value gives no value when the indicator buffer doesn't give a value.
What I need help with is to make the string value for saisignal stay the same when triggered by the indicator buffer, after the bar has passed the arrow indicator, so that when the other signals are eventually indicating a trade, it can trigger a trade.
double closeAllTradesThisPair()
{
for (int i=OrdersTotal();i>=0;i--)
{
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if(OrderSymbol()==Symbol())
{
OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),3,clrNONE);
}
}
}
void OnTick()
{
double saiup = iCustom( Symbol(), PERIOD_H1, "super-arrow-indicator", 0, 0 );
double saidn = iCustom( Symbol(), PERIOD_H1, "super-arrow-indicator", 1, 0 );
double osma1 = iOsMA( Symbol(), PERIOD_H1, 12, 26, 9, PRICE_OPEN, 1 );
double osma0 = iOsMA( Symbol(), PERIOD_H1, 12, 26, 9, PRICE_OPEN, 0 );
double stup = iCustom( Symbol(), PERIOD_H1, "super-trend", 0, 0 );
double stdn = iCustom( Symbol(), PERIOD_H1, "super-trend", 1, 0 );
double sar = iSAR( Symbol(), PERIOD_H1, 0.02, 0.2, 0 );
double ma = iMA( Symbol(), PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE, 0 );
string saisignal = "";
string osmasignal = "";
string stsignal = "";
string sarsignal = "";
string masignal = "";
if(saiup < 1000)
{
saisignal = "123";
}
if(saidn < 1000)
{
saisignal = "321";
}
if(osma1 < osma0)
{
osmasignal = "123";
}
if(osma1 > osma0)
{
osmasignal = "321";
}
if(stup < 1000)
{
stsignal = "123";
}
if(stdn < 1000)
{
stsignal = "321";
}
if(sar < Bid)
{
sarsignal = "123";
}
if(sar > Bid)
{
sarsignal = "321";
}
if(ma < Bid)
{
masignal = "123";
}
if(ma > Bid)
{
masignal = "321";
}
for(int b=OrdersTotal()-1;b>=0;b--)
{
if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
{
if(OrderSymbol()==Symbol())
{
if(OrderType()==OP_BUY)
{
if(OrderStopLoss() < Ask - (150*_Point))
{
OrderModify(OrderTicket(),OrderOpenPrice(),Ask-(150*_Point),OrderTakeProfit(),0,CLR_NONE);
}
}
if(OrderType()==OP_SELL)
{
if(OrderStopLoss() > Bid + (150*_Point))
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid+(150*_Point),OrderTakeProfit(),0,CLR_NONE);
}
}
}
}
}
if(saisignal == "123")
{
if(osmasignal == "123")
{
if(stsignal == "123")
{
if(sarsignal == "123")
{
if(masignal == "123")
{
double buyticket = OrderSend(Symbol(),OP_BUY,0.01,Ask,3,Ask-150*_Point,0,NULL,0,0,CLR_NONE);
}
}
}
}
}
if(saisignal == "321")
{
if(osmasignal == "321")
{
if(stsignal == "321")
{
if(sarsignal == "321")
{
if(masignal == "321")
{
double sellticket = OrderSend(Symbol(),OP_SELL,0.01,Ask,3,Bid+150*_Point,0,NULL,0,0,CLR_NONE);
}
}
}
}
}
Comment(" sai: ",saisignal," osma: ",osmasignal," st: ",stsignal," sar: ",sarsignal," ma: ",masignal);
}
Q : "How do I keep the string value the same...?"
This problem has a single cause and a pair of available steps for solutions:
The OnTick(){...} code as-is, per each entry, creates empty strings. This must be replaced anyway.
But then we have to declare these strings somehow somewhere.
First option
Still let them declared inside the "scope" ( the {...} ) of the OnTick(){...}-code-block, but declare them as static string saisignal = ""; // STATIC modifier is key here, as in this case the static makes the compiler to keep the actual value of such declared variable from one OnTick(){...} call to the other ( so never re-declaring and re-storing the initialiser value (here an empty (string)"") each such time.
#property strict
...
void OnTick(){
...
static string saisignal = "";
static string osmasignal = "";
static string stsignal = "";
static string sarsignal = "";
static string masignal = "";
...
}
Second option
Move such variable declaration onto the "Top-Level" scope (for globally visible variables), which makes compiler reserve a permanent memory location to store and access any such "globally declared/visible" variable(s).
#property strict
string saisignal = "";
string osmasignal = "";
string stsignal = "";
string sarsignal = "";
string masignal = "";
...
void OnTick(){
...
}

ES5 how to implement .Net IEqualityComaparer on data class for comparisons?

When I want to use a custom type T as hash key in .Net, I implement IEqualityComparer and pass it to hash map like Dictionary or HashSet, when adding new item, the GetHashCode and Equals method will be called to check whether two T instance are same.
for example, I have a immutable data class Foo:
sealed class Foo
{
public Foo(int field1, string field2)
{
Prop_1 = field1;
Prop_2 = field2;
}
public int Prop_1 { get; }
public string Prop_2 { get; }
}
and FooEuqalityComparer:
sealed class FooEuqalityComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo x, Foo y)
{
return x == null ? y == null :
x.Prop_1 == y.Prop_1 &&
x.Prop_2 == y.Prop_2;
}
public int GetHashCode(Foo obj)
{
if (obj == null)
return 0;
return obj.Prop_1.GetHashCode() ^ obj.Prop_2.GetHashCode();
}
}
test:
var set = new HashSet<Foo>(new FooEuqalityComparer());
var foo1 = new Foo(1, "foo 1");
var not_foo2 = new Foo(1, "foo 1");
var foo3 = new Foo(3, "foo 3");
set.Add(foo1);
set.Add(not_foo2);
Assert.AreEqual(1, set.Count);
Assert.AreSame(foo1, set.Single());
set.Add(foo3);
Assert.AreEqual(2, set.Count);
How can I do it in nodejs?
Overwrite toString() is not a option because I want to keep reference to that object as key inside map.
After some search, I realized that javascript or ECMAScript use SameValueZero algorithm to compare objects, the best way still is using string as key.
so I use two map to achieve this:
class ObjectKeyMap {
/**
* #param {Object[]} keys -
* #param {function():string} keys[].getHashCode -
* #param {function(Object):T} valueSelector -
*
* #typedef {Object} T
*/
constructor(keys, valueSelector) {
const keyReferences = {};
keys.forEach(it => {
keyReferences[it.getHashCode()] = it;
});
this.keyReferences = keyReferences;
this.map = new Map(keys.map(it => [it.getHashCode(), valueSelector(it)]));
}
/**
* #param {string|{getHashCode:function():string}} key -
*
* #returns {string}
*/
_getStringKey(key) {
if (!key) {
return null;
}
if (Object.prototype.toString.call(key) === "[object String]") {
return key;
} else {
return key.getHashCode();
}
}
/**
* #param {string|{getHashCode:function():string}} key -
*
* #returns {T}
*/
get(key) {
const stringKey = this._getStringKey(key);
if (!stringKey || stringKey === "") {
return null;
}
return this.map.get(stringKey);
}
values() {
return [...this.map.values()];
}
/**
* #param {string|{getHashCode:function():string}} key -
*/
key(key) {
const stringKey = this._getStringKey(key);
if (!stringKey || stringKey === "") {
return null;
}
return this.keyReferences[stringKey];
}
keys() {
return Object.values(this.keyReferences).slice();
}
}
ObjectKeyMap assumes object to be used as key must have a getHashCode function which return identity string. It should be more readable if written in TypeScript.

Resources