Changing an attribute in an object that belongs to RDD - scala

I have the following code :
def generateStoriesnew(outputPath: String, groupedRDD:RDD[(String,Iterable[String])], isInChurnMode: Boolean, isInChurnPeriod: Boolean) {
val windowedRDD = groupedRDD.map(SOME CODE)
var windowedRDD2 = windowedRDD.filter(r => r != null).map(a=>a.churnPeriod(isInChurnPeriod,isInChurnMode))
val prettyStringRDD = windowedRDD2.map(r => {
r.toString
})
prettyStringRDD.saveAsTextFile(outputPath)
}
and here is the code for ChurnPriod function:
def churnPeriod( churnPeriod:Boolean, churnMode: Boolean): Unit = {
if (churnMode && rootEventType.equalsIgnoreCase("c")){
var churnCustStory: CustStoryN = null
var nonChurnCustStory: CustStoryN = null
var churnPeriodEventStory: mutable.MutableList[StoryEventN] = null
var NonChurnEventstory: mutable.MutableList[StoryEventN] = null
churnPeriodEventStory = new mutable.MutableList[StoryEventN]
NonChurnEventstory = new mutable.MutableList[StoryEventN]
var lastEventChurnPeriod = true
var currentEventStory = eventStory
var max = currentEventStory.length
println(max);
if (currentEventStory.size > 0) {
for (i <- 0 until currentEventStory.length) {
var currentEvent = currentEventStory(i)
if (currentEvent.timeSenseRootEvent < 90) {
churnPeriodEventStory.+=(currentEvent)
//lastEventChurnPeriod = true
}
else {
NonChurnEventstory.+=(currentEvent)
lastEventChurnPeriod = false
}
}
}
if (churnPeriod)
eventStory = churnPeriodEventStory
else
eventStory=null
}
}
but churn period function does not change eventstory which is a member of a custstory class. what am I missing here ?
class CustStoryN (val custId:String,
var rootEventType:String,
var rootEventTime:Long,
var eventStory:mutable.MutableList[StoryEventN])
my hypothesis is either:
1.map is not the right transformation for the function that I have
2.churnPeriod function never get called
3.I can not change eventstory which is a member of cust story class
Does anyone have any idea how I can troubleshoot this problem?

This would be trivial to determine by debugging. Just put a few breakpoints and you can see if the program stops inside the function, and what transformations do occur.
My guess would be that the problem is this line: if (currentEventStory.size > 0), thus, a list that starts at size 0 remains at size 0 forever. Another option is that churnPeriod is never true, thus, you compute a lot but never assign to the eventStory variable.
Your code does need a good cleanup ;-)

Related

Placing an apple in snake game written in Scala

To place an apple in an empty place, I'm using the emptySpots() method to locate the points of the cells that are empty or free.
When I implement the code below, my game runs fine:
def emptySpots() : Point = {
val emptyPointsList = new ArrayBuffer[Point]()
var emptyLocation : Point = new Point(0,0)
emptyLocation = Point(random.randomInt(upTo = 25), random.randomInt(upTo = 25))
emptyLocation
}
However, when I try to implement the code below, it shows me errors:
def emptySpots() : Point = {
val emptyPointsList = new ArrayBuffer[Point]()
var emptyLocation : Point = new Point(0,0)
for(i <- 0 until gridDims.height) {
for(j <- 0 until gridDims.width) {
if(getCellType(Point(i, j)) == Empty()) {
emptyPointsList += Point(i, j)
}
}
}
if(!emptyPointsList.isEmpty) {
emptyLocation = emptyPointsList(random.randomInt(emptyPointsList.size))
}
emptyLocation
}
The errors are:
I would appreciate if anyone could point out what's wrong in my second implementation to show me such errors where my first implementation works fine.
P.S. The randomInt() is not wrong here because it's supported by the imported package and library

Change value of variable by reference

Hi I have 4 variables and I want to refer to one of them depending on some conditions, my current code looks as follows:
switch color {
case .Azul:
botonACambiar.tintColor = colores.salidaAzul
if backTees == true {
if option == 1{self.colorHcpBackTees1 = .Azul} else{self.colorHcpBackTees2 = .Azul}
} else {
if option == 1{self.colorHcpFrontTees1 = .Azul} else{self.colorHcpFrontTees2 = .Azul}
}
...
...
case . Cafe:
botonACambiar.tintColor = colores.salidaMarron
if backTees == true {
if option == 1{self.colorHcpBackTees1 = .Cafe} else{self.colorHcpBackTees2 = .Cafe}
} else {
if option == 1{self.colorHcpFrontTees1 = .Cafe} else{self.colorHcpFrontTees2 = .Cafe}
}
}
I have around 8 options, and as you can see it gets kind of messy.
So far I only have 4 different variables that i might manipulate:
Option 1 & 2 for FrontTees & option 1 & 2 for BackTees, but in the future the app might support more options and more colors for front and back tees.
This 4 values are saved in the app and because of this I need to keep track of them individually, thus I have the four variables:
var colorHcpBackTees1: ColoresDeSalidas = .Negra
var colorHcpBackTees2: ColoresDeSalidas = .Blanca
var colorHcpFrontTees1: ColoresDeSalidas = .Roja
var colorHcpFrontTees2: ColoresDeSalidas = .Blanca
Each with their default values, it would be nice to have a way of initializing a reference variable in such a way that I could do something like:
var choice: ColoresDeSalidas{
if backTees && option == 1 { return self.colorHcpBackTees1}
if backTees && option == 2 { return self.colorHcpBackTees2}
if !backTees && option == 1 { return self.colorHcpFrontTees1}
if !backTees && option == 2 { return self.colorHcpFrontTees2}
}
And simply use the variable choice to manipulate the value of the right variable
You can accomplish this using a ReferenceWritableKeyPath.
What is a ReferenceWritableKeyPath?
Think of it as a precise description of a property in a class or struct. A real world example would be The Empire State Building instead of the address which would be 20 W 34th St, New York, NY 10001. You could tell either one to a cab driver and she could take you there.
A ReferenceWritableKeyPath is a generic type. You need to specify the class or struct name and the type of the variable you will be accessing. So your choice variable would be a ReferenceWritableKeyPath<YourClass,ColoresDeSalidas>.
Here is a standalone example:
enum ColoresDeSalidas : String {
case Negra
case Blanca
case Roja
case Azul
case Verde
}
class Foo {
var backTees = false
var option = 1
var colorHcpBackTees1: ColoresDeSalidas = .Negra
var colorHcpBackTees2: ColoresDeSalidas = .Blanca
var colorHcpFrontTees1: ColoresDeSalidas = .Roja
var colorHcpFrontTees2: ColoresDeSalidas = .Blanca
var choice: ReferenceWritableKeyPath<Foo,ColoresDeSalidas> {
if backTees && option == 1 { return \.colorHcpBackTees1 }
if backTees && option == 2 { return \.colorHcpBackTees2 }
if !backTees && option == 1 { return \.colorHcpFrontTees1 }
if !backTees && option == 2 { return \.colorHcpFrontTees2 }
fatalError("We were supposed to return a keyPath for choice")
}
func test() {
backTees = true
option = 2
print("Before: \(self.colorHcpBackTees2)")
// Now update the correct property using the choice KeyPath
self[keyPath: choice] = .Azul
print("After: \(self.colorHcpBackTees2)")
backTees = false
option = 1
// Assign it to another variable, just to show you can
let choiceFront1 = choice
option = 2
// choiceFront1 still refers to !backTees and option 1
// even though option and choice have changed
print("colorHcpFrontTees1 = \(self[keyPath: choiceFront1])")
colorHcpFrontTees1 = .Verde
print("colorHcpFrontTees1 = \(self[keyPath: choiceFront1])")
}
}
Run the test:
Foo().test()
Output:
Before: Blanca
After: Azul
colorHcpFrontTees1 = Roja
colorHcpFrontTees1 = Verde
To clean the code you could wrap the logic for initialising the properties within the enum itself.
extension ColoresDeSalidas {
init?(isBackTee: Bool, option: Int) {
switch (isBackTee, option) {
case (true, 1): self = .colorHcpBackTees1
case (true, 2(: self = .colorHcpBackTees2
case (false, 1): self = .colorHcpFrontTees1
case (false, 2): self = .colorHcpFrontTees2
default: return nil //or assign a default and make non-failable
}
And then you can initialise / update with:
let myVar = ColoresDeSalidas(isBackTee: true, option: 1)

Read first element and next element from a file SCALA

I am reading a file that contain 277272 lines with Int triples (s,p,o) like:
10,44,22
10,47,12
15,38,3
15,41,30
16,38,5
16,44,15
16,47,18
22,38,21
22,41,42
34,44,40
34,47,36
40,38,39
40,41,42
45,38,27
45,41,30
46,44,45
46,47,48
From this file I create a Random access file object in order to navigate trough this file. However I want to extract some specific values that are in the first column, an example can be that I want to extract the values of the row that contains 16 in the first column, then I choose a pointer that is in the half, something like:
var lengthfile = (file.length().asInstanceOf[Int])
var initpointer = lengthfile/2
Then I analize if the first value is 16, if not I did a procedure to move the pointer to the nextlines, or as in this case in the back lines. Once I detect that the first value is 16, I need to know if it was in the first row, the sceond or the last one. The functions that I present here are to get the first value of the line where I have the pointer, and to know the first value from the next line.
def firstvalue(pf: Int, file:RandomAccessFile): List[Int] ={
//val file = new RandomAccessFile(filename, "r")
var pointer = pf
var flag = true
var fline = Option("a")
if (pointer <= file.length()-1){
file.seek(pointer)
fline = Option(file.readLine)
}
else {
pointer = file.length().toInt-12
file.seek(pointer)
fline = Option(file.readLine)
}
while (flag)
{
if (fline.get != "")
{
if (pointer == 0)
{
file.seek(pointer)
fline = Option(file.readLine)
pointer -= 1
flag = false
}
else{
pointer -= 1
file.seek(pointer)
fline = Option(file.readLine)
}
}
else if (fline.get == ""){
flag = false
}
}
pointer += 1
file.seek(pointer)
val line = Option(file.readLine)
val spl = line.get.split(',')
val p = spl.apply(0).toInt
//file.close()
val l = pointer :: p :: Nil
l
}
//def nextvalue(pf: Int, filename:String): List[Int] = {
//val file = new RandomAccessFile(filename, "r")
def nextvalue(pf: Int, file:RandomAccessFile): List[Int] = {
//val file = new RandomAccessFile(filename, "r")
var pointer = pf
var p = 0
var flag = true
var lastline = false
var fline = Option ("a")
if (pointer <= file.length()-1){
file.seek(pointer)
fline = Option(file.readLine)
}
//fline = Option(file.readLine)
while (flag){
if (fline.get != "")
{
if (fline == None)
{
flag = false
lastline = true
}
else{
pointer = file.getFilePointer.toInt
fline = Option(file.readLine)
flag = false
}
}
else if (fline.get == ""){
fline = Option(file.readLine)
flag = false
}
}
if (lastline == false)
{
//file.close()
if (fline != None){
val spl = fline.get.split(',')
p = spl.apply(0).toInt
}
}
val l = pointer :: p :: Nil
l
}
However I have a prformance problem, because I am reading character by character, I am trying to fix that during a lot of days, and I don't have a solution. I don't know If perhaps the file object have a function to read back lines, or something that allows to me improve this code? How can I improve this code?
Source
.fromFile(file)
.getLines
.zipWithIndex
.filter(_._1.startsWith("16,"))
Will give you all lines, that start with "16", along with their indices in the file. That should be faster then seeking back and forth ...

LinkedList in Scala

For exercise I'm trying to implement a LinkedList in Scala.
Main problem is about Null reference.
But first some code:
class Node(xkey: String, xnext: Option[Node], xinfo: Int) {
val key: String = xkey;
var next = xnext.getOrElse(None);
var info: Int = xinfo;
def this(xkey: String, xinfo: Int) {
this(xkey, None, xinfo);
}
def this(xkey: String) {
this(xkey, None, -1);
}
#Override
override def toString: String = key + ":" + info
}
At this point, I'm already concerned about things.
I declare xnext in construct as a Option[Node], because the tail in this linkedList does not have a next.
In my first try, it was just a Node, but had problem with null object because compilator just told me that "null can't cast to Node" (or something like that, I do not remember now) - And so I switch to this Option.
But, is it ok? Because, you know, for me next should be a Node, not a Option, otherwise, I don't know, in the linkedList how to reference to next Node.
Whatever, second class (i.e. my Linked List)
class LinkedNode {
private var first: Option[Node] = None;
private var last: Option[Node] = None;
def addNode(newNode: Node) = {
if (first == null) {
first = Some(newNode);
last = Some(newNode);
first.next = last;
}
else {
last.next = newNode;
newNode.next = null;
last = newNode
}
}
def size(): Long = {
var currentNode : = first;
var size = 0L;
while (currentNode != null) {
size+=1;
currentNode = currentNode.next;
}
size
}
def findNodeByKey(key: String) : Node = {
var currentNode = first;
while(currentNode != null) {
if (currentNode.key.equals(key))
currentNode
else {
currentNode = currentNode.next;
}
}
currentNode;
}
def delNodeByKey(key : String) : Boolean = {
var currentNode = first;
var previousNode = first;
while(currentNode != null) {
if (currentNode.key.equals(key)) {
previousNode = currentNode.next;
return true;
}
previousNode = currentNode;
currentNode = currentNode.next;
}
return false;
}
}
And nothing. I'm already block to my constructor because first and last.
How should I declare them? Node? Or Option[Node]?
Problems are also in Add method.
When I add a node, I want to add a Node object, not an Option[Node].
And I don't get how to achieve things I want with all Option, Some and None classes.
I know I should not be so vague with my request, but any help?
P.S. I've already read this Q/A and it didn't help me
At this point, I'm already concerned about things. I declare xnext in construct as a Option[Node], because the tail in this linkedList does not have a next.
[...]
But, is ok? because, you know, for me next should be a Node, not a Option, otherwise, I don't know, in the linkedList how to reference to next Node.
This is a good solution to replacing null, which you definitely want to do to prevent null-pointer exceptions and the like. An Option[Node] is simply a Node wrapped in a container (or None). You can check whether or not it has a value with isEmpty or get its value with get (which will throw an exception if the Option is empty).
The only difference to null, as you'd use it in Java, is that you need to check if it isEmpty instead of checking for null, and that you need to unwrap (option.get) it explicitly when you're sure that it is not None.
A more paradigmatic (scala-typical) way of retrieving the value from an option is pattern matching:
option match {
case Some(x) => println(x)
case None => println("Whoops, no value :(")
}
Regarding your other questions, they are indeed a little vague.
How should I declere them? Node? or Option[Node]?
Use Option[Node] if the possibility exists that there's no value for the variable (i.e., if you'd set it to null sometimes in Java).
When I add a node, I want to add a Node object, not a Option[Node].
No, you want to add an Option[Node] internally, because you will need to check later on if a node is set or not. In Scala it is preferrable to do this via Option[Node].isEmpty compared to setting things to null. You're already doing this in some parts of your code (e.g., addNode), where you do Some(newNode) (I'd call this "wrapping the node in an Option", but I'm not entirely sure if that's the correct terminology).
And I don't get how to achieve things I want with all Option, Some and None class.
What you're doing in your addNode does seem correct to a degree, but you somehow try to use null again in the else branch. What about:
// We don't need Option[Node] for the parameter, because there
// _must_ be a Node value to be added
def addNode(newNode: Node) = {
if (first.isEmpty) {
first = Some(newNode)
last = Some(newNode)
first.next = last
} else {
newNode.next = None
last.next = Some(newNode)
last = Some(newNode)
}
}
(I didn't run that code, nor did I do an thorough check of your logic)

Erroneous data in some cells of tableview

New to scala and scalafx and having an issue with a tableview in a simple stock quote app [note: no prior javafx experience except in ways it is similar to things Android]
Problem: (see image) erroneous data displayed in change column where there should be none.
To create: Multiple scenarios, shown here is entry of new ticker symbol. It seems unpredictable how many cells are in error. Changing window size (say shorter then taller) generally creates more bad cells. Never happens if no change to windowsize and/or symbol list are made.
Code for the 'ticker' and 'change' columns below, though I suspect it is something in how I implemented the change column to do green/red text coloring.
(Note: data is updated in a single batch periodically which is why the new symbol does not immediately display quote data)
val colTicker = new TableColumn[Quote, String] {
editable = true
text = "Ticker"
prefWidth = 80
alignmentInParent = scalafx.geometry.Pos.Center
cellValueFactory = {
_.value.ticker
}
cellFactory = _ => new TextFieldTableCell[Quote, String](new DefaultStringConverter())
onEditCommit = (evt: CellEditEvent[Quote, String]) => {
val quote: Quote = evt.rowValue
val newTickerVal: String = evt.newValue.toUpperCase()
val oldTickerVal: String = evt.oldValue
// is it a valid ticker and not a dupe or is it blank (erase old ticker)?
if ((isValidTicker(newTickerVal) || newTickerVal.length == 0) && !symbolList.contains(newTickerVal)) {
// lock in the new value on the screen
quote.ticker.set(newTickerVal)
// if the new value is not empty add it to symbol list
if (newTickerVal.length > 0) {
symbolList.append(newTickerVal)
}
// now delete the old value
symbolList -= oldTickerVal
// sort and add another blank line
characters.sortWith(_.ticker.getValueSafe < _.ticker.getValueSafe)
if (oldTickerVal.length < 1) characters += Quote()
// now need to update the data file
putListToFile(dataFile, symbolList.sorted)
} else {
// bad ticker so keep the old one and don't update file
quote.ticker.set(oldTickerVal)
evt.getTableView.getColumns.get(0).setVisible(false)
evt.getTableView.getColumns.get(0).setVisible(true)
println("bad ticker, exiting symbol list: " + symbolList)
}
}
}
val colLast = new TableColumn[Quote, String] {
editable = false
text = "Last"
cellValueFactory = {
_.value.last
}
prefWidth = 80
alignmentInParent = scalafx.geometry.Pos.Center
}
val colChange = new TableColumn[Quote, String] {
editable = false
text = "Change"
cellFactory = {
_ =>
new TableCell[Quote, String] {
item.onChange { (_, _, newChange) =>
if (newChange != null) {
if (newChange.toString.contains("+")) textFill = Color.Green
else textFill = Color.Red
text = newChange
}
}
}
}
cellValueFactory = {
_.value.change
}
prefWidth = 80
alignmentInParent = scalafx.geometry.Pos.Center
}
JavaFX is reusing cells when rendering. This is especially noticeable when dynamically updating TableView content. Your cellFactory has to clear cell content when receiving and empty or null item: text and graphic need to be set to null. It may be sufficient to simply check for newChange == null
cellFactory = { _ =>
new TableCell[Quote, String] {
item.onChange { (_, _, newChange) =>
if (newChange == null) {
text = null
graphic = null
else {
if (newChange.toString.contains("+")) textFill = Color.Green
else textFill = Color.Red
text = newChange
}
}
}
}
It that is nor reliable you will have to implement the cellFactory the JavaFX way by implementing javafx.scene.control.TableCell and overwriting method updateItem that is passing in the empty flag:
cellFactory = {_ =>
new javafx.scene.control.TableCell[Quote, String] {
override def updateItem(item: String, empty: Boolean): Unit = {
super.updateItem(item, empty)
if (item == null || empty) {
text = null
graphic = null
}
else {
...
}
}
}
}