I have a large multi-level switch statement that I'm using to take a table/field ID combination and return a string. Is there a system in dart that is a better choice in regards to read-ability and performance than a switch statement? Is there anything like a mapping or something that I should be using?
This is a snippet of the switch statement which will have 100s of lines when it is done.
switch (tableID)
{
case DBTables.Abbreviations:
switch (fieldID)
{
case TBAbbreviations.ID: result = 'Record ID'; break;
}
break;
case DBTables.Activity:
switch (fieldID)
{
case TBActivity.ID: result = 'Record ID'; break;
case TBActivity.Nickname1: result = 'Nickname'; break;
case TBActivity.Nickname2: result = 'Nickname 2'; break;
case TBActivity.FullName: result = 'Fullname'; break;
case TBActivity.Classification: result = 'Classification'; break;
}
break;
}
return 'Field Name: ' + result ;
You don't write what type tableID and fieldID are but I am guessing they are both int.
I have made the following example which tries to split up the responsibility of the mapping so each table class does its own mapping:
class DBTables {
static const int Abbreviations = 1;
static const int Activity = 2;
static String lookupFieldName(int tableID, int fieldID) {
String result;
if (tableID == Abbreviations) {
result = TBAbbreviations.idToString[fieldID];
} else if (tableID == Activity) {
result = TBActivity.idToString[fieldID];
}
return 'Field Name: $result';
}
}
class TBAbbreviations {
static const int ID = 1;
static const Map<int, String> idToString = {ID: 'Record ID'};
}
class TBActivity {
static const int ID = 1;
static const int Nickname1 = 2;
static const int Nickname2 = 3;
static const int FullName = 4;
static const int Classification = 5;
static const Map<int, String> idToString = {
ID: 'Record ID',
Nickname1: 'Nickname',
Nickname2: 'Nickname 2',
FullName: 'Fullname',
Classification: 'Classification'
};
}
void main() {
print(DBTables.lookupFieldName(DBTables.Activity, TBActivity.FullName)); // Field Name: Fullname
}
You can discuss the placement of DBTables.lookupFieldName but I think it makes sense for my small example.
Related
I'd like to achieve the following C code in Dart:
union AuxiliaryHardwares {
uint16_t all = 0;
struct {
hasRs485: 1;
hasCanbus: 1;
hasRelay0: 1;
hasRelay1: 1;
};
};
AuxialiaryHardwares ah;
ah.all = 123; // Or any value I read from the network
if (ah.hasCanbus) {
// blah blah
}
if (ah.hasRelay0) {
// blah blah
}
There is no language support for accessing individual bits of an integer as an integer or boolean variable.
Traditionally, you'd write it yourself.
class AuxiliaryHardwares {
static const int _rs485Flag = 1;
static const int _canbusFlag = 2;
static const int _relay0Flag = 4;
static const int _relay1Flag = 8;
int all = 0;
bool get hasRs45 => all & _rs45Flag != 0;
bool get hasCanbus => all & _canbusFlag != 0;
bool get hasRelay0 => all & _relay0Flag != 0;
bool get hasRelay1 => all & _relay1Flag != 0;
// Setters too if you want them, e.g.
void set hasRs45(bool value) {
all = value ? (all | _rs45Flag) : (all & ~_rs45Flag);
}
}
You can probably find a bit-set class somewhere which abstracts over accessing individual bits of an integer, but it'll be extra overhead for very little gain.
I expect that "inline classes" will be the future way to encapsulate integers like this.
here is my code
import 'dart:io';
import 'dart:math';
void main() {
bool flag = false;
for (int i = 0; i < 100; i++) {
gameCode();
if (userNumber == computerNumber) {
flag = true;
break;
}
}
}
int randomNumber(number) {
Random randNumber = Random();
int random = randNumber.nextInt(number);
return random;
}
gameCode() {
int computerNumber = randomNumber(9);
print("start guessing the number : ");
int userNumber = int.parse(stdin.readLineSync()!);
if (userNumber == computerNumber) {
print("You got it");
}
}
in this code you can see gameCode function. in that function there is two value that i need to use in main function.so how do i return those two keyword from that function ?
//userNumber // computerNumber
this is the variable that i want to return from that code
Dart not support return multiple values in function, you can return it with array, map, or you can use third lib tuple
Dart does not support returning multiple values in the current latest version. I would in your case recommend creating a class for the specific purpose of define the result from gameCode(). So something like this:
class GameCodeResult {
int userNumber;
int computerNumber;
GameCodeResult({
required this.userNumber,
required this.computerNumber,
});
}
Which we can then use like this in your program:
import 'dart:io';
import 'dart:math';
void main() {
bool flag = false;
for (int i = 0; i < 100; i++) {
GameCodeResult result = gameCode();
if (result.userNumber == result.computerNumber) {
flag = true;
break;
}
}
}
final _random = Random();
int randomNumber(int maxNumber) => _random.nextInt(maxNumber);
GameCodeResult gameCode() {
int computerNumber = randomNumber(9);
print("start guessing the number : ");
int userNumber = int.parse(stdin.readLineSync()!);
if (userNumber == computerNumber) {
print("You got it");
}
return GameCodeResult(userNumber: userNumber, computerNumber: computerNumber);
}
Note, I also fixed your randomNumber() method since it is not recommended to generate a new Random() object for each new random number you want. We should instead reuse an instance of Random in our program.
Please refer to below code
import 'dart:io';
import 'dart:math';
void main() {
bool flag = false;
for (int i = 0; i < 100; i++) {
Map<String, dynamic> res = gameCode();
print(res);
if (res['user_number'] == res['computer_number']) {
flag = true;
break;
}
}
}
int randomNumber(number) {
Random randNumber = Random();
int random = randNumber.nextInt(number);
return random;
}
Map<String, dynamic> gameCode() {
int computerNumber = randomNumber(9);
print("start guessing the number : ");
int userNumber =
int.parse(stdin.readLineSync()!);
if (userNumber == computerNumber) {
print("You got it");
}
return {
"computer_number": computerNumber,
"user_number": userNumber,
};
}
The following code illustrates a logic I need in a Spring Reactive project:
Inputs:
var period = 3;
int [] inArr = {2, 4, 6, 7, 9, 11, 13, 16, 17, 18, 20, 22 };
Calculation:
var upbond = inArr[0] + period;
var count =0;
List<Integer> result = new ArrayList();
for(int a: inArr){
if(a <= upbond){
count++;
}else{
result.add(count);
count = 1;
upbond += period;
}
}
result.add(count);
System.out.println(Arrays.toString(result.toArray()));
The data source of the sorted integers is the Flux from DB where it shall continually fetch data once a new suitable data is written into the DB. And the result shall be a stream that is sending out to another node through RSocket (by the request-stream communication mode).
After some online searching on Reactor, including some tutorials, I still can't figure out how to write the logic in the Flux fashion. The difficulty I have is that those calculations on data defined outside of the loop.
How shall I approach it in the Reactor?
The scan() variant that lets you use a separately typed accumulator is your friend here.
I'd approach this with a separate State class:
public class State {
private int count;
private Optional<Integer> upbond;
private Optional<Integer> result;
public State() {
this.count = 0;
this.upbond = Optional.empty();
this.result = Optional.empty();
}
public State(int count, int upbond) {
this.count = count;
this.upbond = Optional.of(upbond);
this.result = Optional.empty();
}
public State(int count, int upbond, int result) {
this.count = count;
this.upbond = Optional.of(upbond);
this.result = Optional.of(result);
}
public int getCount() {
return count;
}
public Optional<Integer> getUpbond() {
return upbond;
}
public Optional<Integer> getResult() {
return result;
}
}
...and then use scan() to build up the state element by element:
sourceFlux
.concatWithValues(0)
.scan(new State(), (state, a) ->
a <= state.getUpbond().orElse(a + period) ?
new State(state.getCount() + 1, state.getUpbond().orElse(a + period)) :
new State(1, state.getUpbond().orElse(a + period) + period, state.getCount())
)
.windowUntil(s -> s.getResult().isPresent())
.flatMap(f -> f.reduce((s1, s2) -> s1.getResult().isPresent()?s1:s2).map(s -> s.getResult().orElse(s.getCount() - 1)))
Aside: The concatWithValues() / windowUntil() / flatMap() bits are there to handle the last element - there's probably a cleaner way of achieving that, if I think of it I'll edit the answer.
I think scan is definitely the right tool here, combined with a stateful class, although my approach would be slightly different than Michaels.
Accumulator:
class UpbondAccumulator{
final Integer period;
Integer upbond;
Integer count;
Boolean first;
Queue<Integer> results;
UpbondAccumulator(Integer period){
this.period = period;
this.count = 0;
this.upbond = 0;
this.results = new ConcurrentLinkedQueue<>();
this.first = true;
}
//Logic is inside accumulator, since accumulator is the only the only thing
//that needs it. Allows reuse of accumulator w/o code repetition
public UpbondAccumulator process(Integer in){
//If impossible value
//Add current count to queue and return
//You will have to determine what is impossible
//Since we concat this value on the end of flux
//It will signify the end of processing
//And emit the last count
if(in<0){
results.add(count);
return this;
}
//If first value
//Do stuff outside loop
if(this.first) {
upbond = in + period;
first=false;
}
//Same as your loop
if(in <= upbond)
count++;
else {
results.add(count);
count = 1;
upbond += period;
}
//Return accumulator
//This could be put elsewhere since it isn't
//Immediately obvious that `process` should return
//the object but is simpler for example
return this;
}
public Mono<Integer> getResult() {
//Return mono empty if queue is empty
//Otherwise return queued result
return Mono.justOrEmpty(results.poll());
}
}
Usage:
dbFlux
//Concat with impossible value
.concatWithValues(-1)
//Create accumulator, process value and return
.scan(new UpbondAccumulator(period), UpbondAccumulator::process)
//Get results, note if there are no results, this will be empty
//meaning it isn't passed on in chain
.flatMap(UpbondAccumulator::getResult)
Following comment from Michael here is an immutable approach
Accumulator:
public class UpbondAccumulator{
public static UpbondState process(int period,Integer in,UpbondState previous){
Integer upbond = previous.getUpbond().orElse(in + period);
int count = previous.getCount();
if(in<0) return new UpbondState(upbond, count, count);
if(in <= upbond) return new UpbondState(upbond,count + 1 , null);
return new UpbondState(upbond + period, 1, count);
}
}
State object:
public class UpbondState {
private final Integer upbond;
private final int count;
private final Integer result;
public UpbondState() {
this.count = 0;
this.upbond = null;
this.result = null;
}
public UpbondState(Integer upbond, int count,Integer result) {
this.upbond = upbond;
this.count = count;
this.result = result;
}
public int getCount() { return count; }
public Optional<Integer> getUpbond() { return Optional.ofNullable(upbond); }
public Integer getResult() { return result; }
public boolean hasResult() { return result!=null; }
}
Usage:
dbFlux
.concatWithValues(-1)
.scan(new UpbondState(),
(prev, in) -> UpbondAccumulator.process(period,in,prev))
//Could be switched for Optional, but would mean one more map
//+ I personally think makes logic less clear in this scenario
.filter(UpbondState::hasResult)
.map(UpbondState::getResult)
Dart allows variables of types: Type type = SomeType; But for what purpose?
For example, foo bar baz are misapplications:
class A {
Type type = List;
foo() => new type();
type bar() {
return new List();
}
type baz = new List();
}
void main() {
Type type = String;
var str = "Hello Dart";
print(type == str.runtimeType);//true
print(str is String);//true
print(str is type); //type error.
}
I think this one is pretty neat:
void main() {
foo(Type t) {
switch (t){
case int: return 5;
case List: return [1,2,3]; // This one gets me every time :(
case String: return "Hello Dart!";
default: return "default";
}}
print(foo(10.runtimeType)); //5
print(foo([2,4,6].runtimeType)); //default
print(foo("lalala".runtimeType)); //Hello Dart!
print(foo(foo.runtimeType)); //default
}
Is its sole purpose to be the return type for methods like runtimeType and type matching ?
I don't think you can use it for generics. There you need type literals. But you can use it for reflection.
Just one simple example:
import 'dart:mirrors' as mirr;
class A {
String s;
A(this.s);
#override
String toString() => s;
}
void main() {
Type type = A;
var str = "Hello Dart";
mirr.ClassMirror cm = mirr.reflectType(type);
var s = cm.newInstance(new Symbol(''), [str]).reflectee;
print(s);
}
You could also create a Map with registered factories for different types to avoid the need for reflection.
(not tested)
class A {
String s;
int a = 0;
int b = 0;
int c = 0;
A(this.s);
A.extended(this.s, this.a, this.b, this.c);
#override
String toString() => '${super.toString()}: $s, $a, $b, $c';
}
void main(args) {
Type t = A;
registerType(t, (List args) => new A.extended(args[0], args[1], args[2], args[3]));
...
var a = getInstance(t, ['hallo', 1, 2, 3]);
}
Map<Type,Function> _factories = {};
void registerType(Type t, Function factory) {
_factories[t] = factory;
}
void getNewInstance(Type t, List args) {
return _factories[t](args);
}
I keep getting the error message "identifyer expected" on this line: hk.guess(charToGuess);
what do I need to do to correct that?
I am creating a simple Hangman game and it is giving me a lot of trouble. I am very new at programming and I am starting to feel very over-whelmed by this project.
import java.util.Random;
import java.util.Scanner;
import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Hangman {
public static void main( String[] args ) {
HangmanSession hangmanSession = new HangmanSession();
hangmanSession.play();
}
private HiddenKeyword hiddenKeyword;
private int triesNumber = 7;
hiddenKeyword hk = new HiddenKeyword();
hk.guess(charToGuess);
private void printState() {
System.out.print( "Hidden word : " );
hiddenKeyword.print();
System.out.print( "Tries left: " + triesNumber + "\n<guess letter:>" );
}
public void play() {
boolean bool = true;
while( true ) {
bool = true;
printState();
System.out.println( "Try again, you've already used that letter " + char.class );
bool = false;
}
if( bool ) {
if( hiddenKeyword.guess( char.class ) ) {
System.out.println( "YAY! you have found letter! " + ch );
}
else {
triesNumber--;
}
if( triesNumber < 1 )
gameOver();
if( hiddenKeyword.found() )
congratulations();
}
} //end of bool
public void congratulations() {
System.out.println( "Congratulations " + player + ", you win!" );
System.exit( 0 );
}
public void gameOver() {
System.out.println( "Sorry " + player + ", you lost, but you can try again!" );
System.exit( 0 );
}
private String fValue;
private StringBuffer pValue;
private int lfoundNumber = 0;
public String words() {
Random r = new Random();
int random = r.nextInt(20)+1;
}
public boolean found() {
System.out.println( "Letters found:" + lfoundNumber + "/" + fValue.length() );
return ( lfoundNumber == fValue.length() );
}
public boolean guess( char c ) {
int index = fValue.indexOf( c );
if( index == -1 )
return false;
else {
lfoundNumber = lfoundNumber + findOccurances( c );
return true;
}
}
private int findOccurances( char c ) {
int idx = fValue.indexOf( c );
pValue.setCharAt( idx, fValue.charAt( idx ) );
int counter = 1;
while( idx != -1 ) {
int idxx = fValue.indexOf( c, idx + 1 );
idx = idxx;
if( idx != -1 ) {
counter++;
pValue.setCharAt( idx, fValue.charAt( idx ) );
}
}
return counter;
}
public void print() {
System.out.println( pValue );
}
private char[] lbox = new char[24];
private int counter = 0;
public boolean contains( char c ) {
for( int i = 0; i < counter; i++ ) {
if( lbox[i] == c )
return true;
}
lbox[counter] = c;
counter++;
return false;
}
public void print() {
System.out.print( "\nLetterBox:" );
for( int i = 0; i < counter; i++ ) {
System.out.print( lbox[i] );
}
System.out.println( "" );
}
public static void main(String[] args) {
int words = 20;String wordsString;
switch(random) {
case 1:
return "star";
case 2:
return "hooray";
case 3:
return "dog";
case 4:
return "improvise";
case 5:
return "teacher";
case 6:
return "college";
case 7:
return "seahawks";
case 8:
return "read";
case 9:
return "computer";
case 10:
return "program";
case 11:
return "holiday";
case 12:
return "film";
case 13:
return "music";
case 14:
return "learn";
case 15:
return "library";
case 16:
return "waterfall";
case 17:
return "book";
case 18:
return "semester";
case 19:
return "first";
case 20:
return "vacation";
default:
return"";
}
}
}
}
Remember, as a rule of thumb in Java, that a class may contain only fields and methods. Statements (except maybe those that initialize a field to a default value) can only be written inside methods.
With the above in mind, the problem is that you are simply invoking a method (hk.guess(charToGuess)) inside the class but not inside any method and that statement is not a field initializer.