Convolution decoding using viterbi algorithm in unetstack - viterbi

I have tried to implement convolution decoding using Viterbi algorithm in unetstack. However, there are some issues that I am facing.
The data is not getting sent to node 2. (arr - line 43 of MulAgent.groovy )
In some cases getting an error-
groovy.lang.MissingMethodException:No signature of method:Script2.send() is applicable for argument types:(java.lang.Integer, java.lang.Integer)
values: [2,1010]
//where 2, 1010 are the input values that we are giving
mul-sim.groovy(first file that opens and asks for input of data)
import org.arl.fjage.Message
import org.arl.unet.*
import org.arl.mac.*
import org.arl.unet.phy.*
import org.arl.fjage.RealTimePlatform
println'''
OUTPUT TABLE
+----+----------+----------+
| | 0 | 1 |
+----+----------+----------+
| a | 00(a) | 11(b) |
+----+----------+----------+
| b | 10(c) | 01(d) |
+----+----------+----------+
| c | 11(a) | 00(b) |
+----+----------+----------+
| d | 01(c) | 10(d) |
+----+----------+----------+ '''
println '''
2-node network to perform sender - receiver operation
-----------------------------------------
Node 1 will send an encoded value to node 2
The agent MulAgent present at node 2, will decode the received data and send the value to node 1 checking
You can interact with node 1 in the console shell. For example, try:
send <to-address> , < data>
For example:
send 2, 1011
When you are done, exit the shell by pressing ^D or entering:
shutdown
'''
platform = RealTimePlatform
// run simulation forever
simulate {
node '1', address: 1, remote: 1101, location: [0, 0, 0], shell: true, stack: { container ->
container.shell.addInitrc "${script.parent}/fshrc.groovy"
}
node '2', address: 2, remote: 1102, location: [1.km, 0, 0], shell:5102, stack: { container ->
container.add 'mul', new MulAgent()
}
}
MulAgent.groovy( Agent file
//Agent for the program that contains the decoding code
import org.arl.fjage.Message
import org.arl.unet.*
import org.arl.mac.*
class MulAgent extends UnetAgent {
final static int PROTOCOL = Protocol.DATA
int received_data
int new_data
def arr = new int[4][2]
def temp = new int[2]
def code=new int[4][2]
int i
int k
int j = 0
int error_bit;
int column_error = 0
int row_error = 0
int m = 4
int n = 4
int count
void startup() {
def phy = agentForService Services.PHYSICAL
subscribe topic(phy)
}
void processMessage(Message msg) {
if (msg instanceof DatagramNtf && msg.protocol == PROTOCOL)
{
for(i=0;i<2;i++)
{
temp[i] = msg.data[i]
println "Recieved data printing in Agent is ${temp[i]}"
}
for(i=0;i<2;i++)
arr[j][i] = temp[i];
println "Array in Agent is ${arr}}"
println "Recieved data printing in Agent is ${temp}"
println "Recieved total data printing in Agent is ${temp}"
send new DatagramReq(recipient: msg.sender,to: msg.from, protocol: Protocol.MAC, data: arr[j])
j++
// start
/*******************************************************************/
/* /
/ convolution decoding using viterbi /
/ ------------------------------------------ /
/ Step 1: take input as the encoded dataword /
/ Step 2: Sub module to calculate hamming distance /
/ Step 2: code for decoding using viterbi algorithm */
/*******************************************************************/
code=arr;
int state[]=[0,,0,0,0,0,0,0] //state
int mem[]=[0,0,0,0,0,0,0,0,0,0] //memory
int path=0; //path matrix
//int data[]=[1,1,0,1]
int n,l;
for (int j=0;j<4;j++)
{ for(int i=8;i>=0;i--)
{ mem[i+i]=mem[i]; //shifting by one bit
}
for (int i=0;i<8;i++)
{ state[i]=mem[i];
}
//disp(mem);
state[i]=0; //introduce 0
mem[i]=0;
// to calculate the hamming distance
int out1=((mem[1]^mem[2]^mem[4]^mem[5]^mem[6]^mem[7]^mem[8])^ ((mem[1]^mem[2]^mem[3]^mem[5]^mem[6]^mem[7]^mem[8])); //disp(out1); //output with 0
state[i]=1; //introduce 1
mem[i]=1;
int out2=((mem[1]^mem[2]^mem[4]^mem[5]^mem[6]^mem[7]^mem[8])^ ((mem[1]^mem[2]^mem[3]^mem[5]^mem[6]^mem[7]^mem[8]));
int l=(code[j][0]^out1)+(code[j][1]^out)); //hamming distance with out1
int m=(code[j][0]^out2)+(code[j][1]^out2)); //hamming distance with out2
if(l<m) { //consider with minimum hamming distance
path=path+l;
state[1]=0;
mem[1]=0;
data[j]=0;}
else
{ path=path+m;
data[j]=1;
}
if(l<m)
{ path=path+l;
decode[k]=0;}
else if(l>m)
{ path=path+m;
decode[k]=1;
}
println"path value =$path"
int code=data;
}
def codew=new int[4][2]
codew=code;//detecting 0 bit error
int correct=0;
int detect=0;
int n;
for(i=0;i<2;i++)
if(codew[i][j])
codew[i][j]=0;
for(int i=0;i<4;i++)
if(path!=0) //one error detected
{ if(y==codew) //corrected
{ correct=correct+1;
detect=detect+1;
}
}
if(path!=0) //detected
{ if(y!=codew) //not corrected
{ detect=detect+1;
}
}
n++;
if(codew[i][j])
codew[i][j]=0;
else
codew[i][j]=1;
}
if(detect==0)
println"detection completed"
println"$code"
else if(detect!=0)
println"detection completed"
println"$code"
}
}
fshrc.groovy (the received word is encoded and sent for decoding)
import org.arl.unet.*
import org.arl.unet.phy.*
import org.arl.unet.*
import org.arl.unet.phy.*
import org.arl.unet.mac.*
//import org.arl.unet.nodeinfo.NodeInfo
//import org.arl.unet.PDU
import org.arl.fjage.*
//import static org.arl.unet.Services.*
//import static org.arl.unet.phy.Physical.*
subcribe phy
send = { addr, value ->
println "sending $value to node $addr"
def y= new int[4];
def a=new int[4];
a=[1, 1, 1, 1]
y=[0, 0, 0, 0]
int i=3
println "$value"
int x=value;
while(x!=0)
{
y[i]=x%10;
println "$y"
x=x/10;
i--;
}
def code=new int[4][2];
/*code word encoded using generator functions
g1=1101
g2=1110
*/
for(i=0;i<4;i++)
{
int bit = y[3-i];
a[3-i] = bit;
code[i][0] = a[0]^a[1]^a[3];
code[i][1] = a[0]^a[1]^a[2];
}
println"The 4 bit encoded codeword:"
//The code word is printed
println"$code"
//println "sending ${value[0]} to node $addr "
phy << new DatagramReq(to: addr, protocol: Protocol.DATA, data: code[0])
def txNtf1= receive(TxFrameNtf, 1000)
def rxNtf1 = receive({ it instanceof RxFrameNtf && it.from == addr}, 5000)
if (txNtf1 && rxNtf1 && rxNtf1.from == addr)
println "Data Received at ${rxNtf.to} from ${rxNtf.from} is: ${rxNtf.data}"
//println "sending ${value[1]} to node $addr "
phy << new DatagramReq(to: addr, protocol: Protocol.DATA, data: code[1])
def txNtf2 = receive(TxFrameNtf, 1000)
def rxNtf2 = receive({ it instanceof RxFrameNtf && it.from == addr}, 5000)
if (txNtf2 && rxNtf2 && rxNtf2.from == addr)
println "Data Received at ${rxNtf2.to} from ${rxNtf2.from} is: ${rxNtf2.data}"
// println "sending ${value[2]} to node $addr "
phy << new DatagramReq(to: addr, protocol: Protocol.DATA, data: code[2])
def txNtf3 = receive(TxFrameNtf, 1000)
def rxNtf3 = receive({ it instanceof RxFrameNtf && it.from == addr}, 5000)
if (txNtf3 && rxNtf3 && rxNtf3.from == addr)
println "Data Received at ${rxNtf3.to} from ${rxNtf3.from} is: ${rxNtf3.data}"
//println "sending ${value[3]} to node $addr "
phy << new DatagramReq(to: addr, protocol: Protocol.DATA, data: code[3])
def txNtf4 = receive(TxFrameNtf, 1000)
def rxNtf4 = receive({ it instanceof RxFrameNtf && it.from == addr}, 5000)
if (txNtf4 && rxNtf4 && rxNtf4.from == addr)
println "Data Received at ${rxNtf4.to} from ${rxNtf4.from} is: ${rxNtf4.data}"
}

Related

trying to deserialize JSON unsuccesfully

I am trying to deserialize an array of chars using the ArduinoJson Lib. The chars are coming from a I2C connection using Wire library. They come successfully so I don't think there is an issue there.
When trying to de-serialize at run time I get the message "deserializeJson() failed: EmptyInput".
From ArduinoJson Troubleshooter's report
The issue happens at run time
The issue concerns deserialization
deserializeJson() returns EmptyInput
Input comes neither from an HTTP response, nor a file, nor a stream
The part of code that deserialization fails is here:
void callback(char payload[], unsigned int msg_size) {
Serial.print("Message arrived ");
for (int i=0;i<msg_size;i++) {
Serial.print((payload[i]));
}
DeserializationError error = deserializeJson(doc, payload, msg_size);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
const char* command = doc["cmd"];
Serial.print("command ");
Serial.println(command);
//rest of code
}
void setup() {
//communications
Wire.begin(0x8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
Serial.print("Start_");
Serial.println(ver);
}
void loop() {
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
char buff[60];
Serial.print("how many=");
Serial.println(howMany);
//initialize buffers
buff[0] = '\0';
int i = 0;
while (0 < Wire.available()) { // loop through all but the last
//char c = Wire.read(); // receive byte as a character
char c = Wire.read();
Serial.print(c); // print the character
buff[i] = c;
buff[i+1] = '\0'; // Add a NULL after each character
i++;
}
int x = Wire.read(); // receive byte as an integer
Serial.println();
Serial.print("x:");
Serial.println(x); // print the integer
Serial.print("BUFFER:");
for (int j=0; j < howMany; j++) {
Serial.print(buff[j]);
}
Serial.println();
Serial.print("size:");
Serial.println(sizeof(buff));
callback(buff, howMany);
}
The print out from serial ide is here:
Start_v.0.1
how many=25
{"cmd":"demo","seq":"1"}
x:-1
BUFFER:{"cmd":"demo","seq":"1"}
size:60
Message arrived {"cmd":"demo","seq":"1"} deserializeJson() failed: EmptyInput
But the payload variable, as you see here is not empty.
Can you provide any debugging hints? Thank you
Edit: I have added more code that shows the i2c communication
from smbus import SMBus
addr = 0x8 # bus address
bus = SMBus(1) # indicates /dev/ic2-1
numb = 1
def StringToBytes(val):
retVal = []
for c in val:
retVal.append(ord(c))
return retVal
def writeData(arrayValue, i2c_address):
byteValue = StringToBytes(arrayValue)
# examples --->
bus.write_i2c_block_data(i2c_address,0x00,byteValue)
return -1
# main
print ("Enter command:")
while 1:
cmd = input(">>>> ")
writeData(str(cmd), addr)
I filtered the incoming i2c buffer for nulls and the de serialization of JSON worked. I am not sure why the nulls are sent by rpi/python.
void receiveEvent(int howMany) {
char buff[60];
Serial.print("how many=");
Serial.println(howMany);
//initialize buffers
buff[0] = '\0';
int i = 0;
while (0 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
if (c == '\0') {
//ignore
} else {
//char c = Wire.read();
Serial.print(c); // print the character
buff[i] = c;
buff[i+1] = '\0'; // Add a NULL after each character
i++;
}
}
int x = Wire.read(); // receive byte as an integer
Serial.println();
Serial.print("x:");
Serial.println(x); // print the integer
Serial.print("BUFFER:");
for (int j=0; j < howMany; j++) {
Serial.print(buff[j]);
}
Serial.println();
Serial.print("size:");
Serial.println(sizeof(buff));
callback(buff, howMany);
}

Executing function upon required number of times

calculate the sum of squares of given integers, excluding any negatives.
The first line of the input will be an integer N (1 <= N <= 100), indicating the number of test cases to follow.
Each of the test cases will consist of a line with an integer X (0 < X <= 100), followed by another line consisting of X number of space-separated integers Yn (-100 <= Yn <= 100).
For each test case, calculate the sum of squares of the integers, excluding any negatives, and print the calculated sum in the output.
Note: There should be no output until all the input has been received.
Note 2: Do not put blank lines between test cases solutions.
Note 3: Take input from standard input, and output to standard output.
Rules
Write your solution using Go Programming Language
Your source code must be a single file (package main)
Do not use any for statement
You may only use standard library packages
"Problem which I am facing"
'square' function below is not getting executed the required number of times according to the input test cases. To meet specific requirements I wasn't allowed to use the 'for' statement. Please help me out. Language is Go.
package main
import "fmt"
var s []int
func square(l int) {
i := 0
sum := 0
Square:
if l > 0 {
s[i] = s[i] * s[i]
sum = sum + s[i]
i++
l--
goto Square
}
fmt.Println(sum)
}
func myfunc(a int) {
Here:
if a > 0 {
var b int
fmt.Scanln(&b)
if b > 0 {
s = append(s, b)
}
a--
goto Here
}
}
func main() {
var a int
fmt.Scanln(&a)
TestCases:
if a > 0 {
var T int
fmt.Scanln(&T)
myfunc(T)
a--
goto TestCases
}
square(len(s))
}
Here is an implementation using recursion:
package main
import "fmt"
func testCase(N int) {
if N <= 0 {
return
}
var X int
fmt.Scanf("%d", &X)
fmt.Println(sumOfSquare(X))
testCase(N-1)
}
func sumOfSquare(X int) int {
if X == 0 {
return 0
}
var Y int
fmt.Scanf("%d", &Y)
if Y > 0 {
return Y*Y + sumOfSquare(X-1)
}
return sumOfSquare(X-1)
}
func main() {
var N int
fmt.Scanf("%d", &N)
testCase(N)
}
Here is an example output:
$ go run main.go
2 4 3 -1 1 14 5 9 6 -53 32 16
206
1397
I have this program in python using recursion, but not in go-lang.
Here is the code
def squaresum(counter,alist):
if counter==0:
return 0
else:
if int(alist[counter-1])<0:
return 0 + squaresum(counter-1, alist)
else:
return int(alist[counter-1])**2 + squaresum(counter-1,alist)
def testcase(a):
if a==0:
return
terms = int(input())
nums = input()
list1 = nums.split()
print(squaresum(terms,list1))
testcase(a-1)
if __name__=='__main__':
casecount = int(input())
testcase(casecount)

Boost.log create text file backend manually

Logger.h
enum ChannelType {
main_channel,
sub_channel
};
BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", ChannelType)
class Logger {
public:
enum severity_level
{
debug,
info,
warning,
error,
fatal
};
static void init(Logger::severity_level level);
typedef boost::log::sources::severity_channel_logger< Logger::severity_level, ChannelType > logger_type;
static thread_local logger_type gl;
static thread_local logger_type motion_checker;
};
Logger.cpp
void Logger::init(Logger::severity_level level)
{
boost::shared_ptr<boost::log::core> core = boost::log::core::get();
core->set_exception_handler(boost::log::make_exception_suppressor());
core->set_filter(boost::log::expressions::attr<Logger::severity_level>("Severity") >= level);
{
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_multifile_backend> multifile_sink;
boost::shared_ptr<multifile_sink> sink(new multifile_sink);
sink->locked_backend()->set_file_name_composer(boost::log::sinks::file::as_file_name_composer(
boost::log::expressions::stream << "./log/Sub/" << boost::log::expressions::attr< std::string >("RoleName") << ".log"));
sink->set_formatter
(
boost::log::expressions::format("[%1%] - %2%")
% boost::log::expressions::attr< boost::posix_time::ptime >("TimeStamp")
% boost::log::expressions::smessage
);
sink->set_filter(channel == sub_channel);
core->add_sink(sink);
}
//============use add_file_log==============
boost::log::add_file_log(
boost::log::keywords::filter = channel == main_channel,
boost::log::keywords::file_name = "./log/%Y%m%d.log",
boost::log::keywords::auto_flush = true,
boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
boost::log::keywords::format = "[%TimeStamp%] (%LineID%) {%ThreadID%}: %Message%"
);
//==================use add_file_log end====================
//=========manually add sink, this has problem================
boost::shared_ptr< boost::log::sinks::text_file_backend > backend =
boost::make_shared< boost::log::sinks::text_file_backend >(
boost::log::keywords::filter = channel == main_channel,
boost::log::keywords::file_name = "./log/%Y%m%d.log",
boost::log::keywords::auto_flush = true,
boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
boost::log::keywords::format = "[%TimeStamp%] (%LineID%) {%ThreadID%}: %Message%"
);
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend> file_sink;
boost::shared_ptr< file_sink > sink(new file_sink(backend));
core->add_sink(sink);
//============manually add end==========================
boost::log::add_common_attributes();
}
thread_local Logger::logger_type Logger::gl(boost::log::keywords::channel = main_channel);
thread_local Logger::logger_type Logger::motion_checker(boost::log::keywords::channel = sub_channel);
main.cpp
int main()
{
Logger::init(Logger::debug);
BOOST_LOG_SEV(Logger::gl, Logger::debug) << "ssss";
{
BOOST_LOG_SCOPED_LOGGER_ATTR(Logger::motion_checker, "RoleName", boost::log::attributes::constant< std::string >("aaa"))
BOOST_LOG_SEV(Logger::motion_checker, Logger::debug) << "aaaa";
}
system("pause");
return 0;
}
Using add_file_log, every thing is OK, but the manually add sink lost all attributes, only message in there. And the filter is also not work, sub_channel message will add to this file. The reason I create this file sink manually is because add_file_log create sync sink, I want a async sink.
The problem is that the named parameters format and filter are used by the sink frontend, not the backend, and you pass them to the backend. As a result neither filter nor formatter are set.
I suggest you move all named parameters to the sink frontend constructor and let it pass the parameters to the backend constructor instead of constructing the backend yourself.
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend> file_sink;
boost::shared_ptr< file_sink > sink = boost::make_shared< file_sink >(
boost::log::keywords::filter = channel == main_channel,
boost::log::keywords::file_name = "./log/%Y%m%d.log",
boost::log::keywords::auto_flush = true,
boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
boost::log::keywords::format = "[%TimeStamp%] (%LineID%) {%ThreadID%}: %Message%"
);
core->add_sink(sink);

msgrcv() function not returning in client process

My program is based on interprocess communication. The client send a filename which the server reads and returns its contents back to the client. The msgsnd() function seems to be working but there is no return to the client function when msgrcv() is invoked to read the files contents.
Here is my client program :
#include<sys/msg.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<string.h>
#include<stdio.h>
#include<fcntl.h>
#define MSGSIZE 10000
typedef struct
{
long mtype;
char msgtext[MSGSIZE];
} msg_buf;
int main()
{
int msgflag=IPC_CREAT | 0666;
key_t k1, k2;
msg_buf buf;
k1 = 1234;
k2 = 5678;
int msgqid1, msgqid2;
if(msgqid1=msgget(k1,msgflag)<0)
{
printf("\nClient online : the output message queue isn't available. Restart !\n");
return 0;
}
else
{
printf("\nClient online : the output message queue is available.\n Enter the file name : ");
scanf("%s",buf.msgtext);
}
buf.mtype = 1;
if(msgqid2=msgget(k2,msgflag)<0)
printf("\nClient: Input message queue unavailable. Restart !\n");
else
printf("\nClient : Input message queue available \n");
int buf_len = strlen(buf.msgtext)+1;
printf("Client: Sending file name : %s \n",buf.msgtext);
if(msgsnd(msgqid1,&buf,buf_len,IPC_NOWAIT)<0)
{
printf("Client : Error sending file name\n");
return 0;
}
printf("hello\n");
if((msgrcv(msgqid2,&buf,MSGSIZE,2,0))<0)
{
printf("Client : Error Recieving file contents from server\n");return 0;
}
else
{
printf("File Contents from the server as follows :\n ");
fputs(buf.msgtext,stdout);
printf("\n\n");
}
}
Here is my server program:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#define MSGSIZE 10000
typedef struct msg_buf
{
long mtype;
char msgtext[MSGSIZE];
} msg_buf;
int main()
{
msg_buf buf;
key_t k1, k2;
int filesize, fileread, msgqid1, msgqid2;
k1 = 1234;
k2 = 5678;
int msgflag=IPC_CREAT | 0666;
if((msgqid1=msgget(k1,msgflag))<0)
{
printf("Server Online :Input message queue not available. Restart !\n");
return 0;
}
printf("Server Online :Input message queue available.\n");
if((msgrcv(msgqid1,&buf,MSGSIZE,1,0))<0)
{
printf("Server : Error receiving file name");
return 0;
}
printf("Server : File name %s received. \n",buf.msgtext);
if((msgqid2=msgget(k2,msgflag))<0)
{
printf("Server : Output message queue not available. Restart !\n");
return 0;
}
else
printf("Server Online : Output message queue available.\n");
fileread = open(buf.msgtext,O_RDONLY);
if(fileread<0)
{
printf("Server : File not found,%d \n",fileread);
return 0;
}
buf.mtype = 2;printf("Server : file found\n");
filesize = lseek(fileread,0,2);
lseek(fileread,0,0);
int n = read(fileread,buf.msgtext,filesize);
int buf_len = strlen(buf.msgtext)+1;
fputs(buf.msgtext,stdout);
if(msgsnd(msgqid2,&buf,buf_len,IPC_NOWAIT)>=0)
printf("Server : contents of the file sent to the client\n");
else
{
printf("Server : Error on sending file contents \n");
return 0;
}
}

get next Row when importing file CSV with grails

i am trying to import file CSV like this image..
this image means..
when i import this file..line 1 with read and save in to Table SeniorHighSchool
then it will get :
name : Alexander
age : 15
muchcourse : 3
after that i want make a condition, When "muchcourse is filled" it will read the next row...
example :
at this case, the "muchcourse" is "3", then "look at the image"..row 2,3,4 (3 lines)will inserted to other table .. because the "muchcourse" is "3"
this is my coding what i have tried .
def upload = {
withForm{
def f = request.getFile('filecsv')
def orifilename = f.getOriginalFilename()
def homeDir = new File(System.getProperty("user.home"))
def homeurl = "Documents/Uploads/"
File fileDest = new File(homeDir,homeurl+orifilename)
f.transferTo(fileDest)
request.getFile(new File(fileDest)).InputStream.splitEachLine(',') {fields ->
def student= new SeniorHighSchool(
name: fields[0].trim(),
age: fields[1].trim(),
muchcourse: fields[2].trim()
)
if (student.hasErrors() || student.save(flush: true) == null)
{
log.error("Could not import domainObject ${student.errors}")
}
}
redirect(action:"list")
}
}
i confused to make a condition..
def upload = {
withForm{
def f = request.getFile('filecsv')
def orifilename = f.getOriginalFilename()
def homeDir = new File(System.getProperty("user.home"))
def homeurl = "Documents/Uploads/"
File fileDest = new File(homeDir,homeurl+orifilename)
f.transferTo(fileDest)
request.getFile(new File(fileDest)).InputStream.splitEachLine(',') {fields ->
def student= new SeniorHighSchool(
name: fields[0].trim(),
age: fields[1].trim(),
muchcourse: fields[2].trim()
)
if (student.hasErrors() || student.save(flush: true) == null)
{
log.error("Could not import domainObject ${student.errors}")
}
if(fields[2]) {
def score = new Score(
course: //the problem at this line..how?
//it will insert 3 times then back to the row 5 to insert into "Student" again
)
}
}
redirect(action:"list")
}
}
if(fields.size()>2){
store 3 values in one table(student)
}
else{
store 2 values in another table(score)
}
If muchcourse field is occured then fields size is 3 then save three data in one table. otherwise size is 2 then save that two data in another table.I think it will solve your problem.
#th3morg like thiss?
request.getFile(new File(fileDest)).InputStream.splitEachLine(',') {fields ->
if(fields.size()>2){
def student= new SeniorHighSchool(
name: fields[0].trim(),
age: fields[1].trim(),
muchcourse: fields[2].trim()
)
}
else{
def score = new Score(
course:fields[0].trim(),
score:fields[1].trim()
)
}
}
If the class SeniorHighStudent "static hasMany = [scores: Score]" then the following should do the trick:
def currentStudent
request.getFile(new File(fileDest)).InputStream.splitEachLine(',') {fields ->
if(fields.size()>2){
if(currentStudent){
/*we've found a new student, so save the previous one*/
currentStudent.save()
}
currentStudent = new SeniorHighSchool(
name: fields[0].trim(),
age: fields[1].trim(),
muchcourse: fields[2].trim()
)
}
else{
/*add the score to the currentStudent's scores*/
currentStudent.addToScores(new Score(
course:fields[0].trim(),
score:fields[1].trim()
))
}
}
/*when the loop is done, save the last student because it hasn't been saved yet*/
currentStudent.save()