<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Prdesai2</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Prdesai2"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Prdesai2"/>
	<updated>2026-10-10T18:23:14Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_M1501_Report_CSS_errors_to_the_devtools,_both_stored_and_live&amp;diff=99158</id>
		<title>CSC/ECE 517 Fall 2015 M1501 Report CSS errors to the devtools, both stored and live</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_M1501_Report_CSS_errors_to_the_devtools,_both_stored_and_live&amp;diff=99158"/>
		<updated>2015-11-09T21:19:15Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Added links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Rust_(programming_language) Rust] is a programming language developed by [http://en.wikipedia.org/wiki/Mozilla Mozilla]. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo] is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;br /&gt;
&lt;br /&gt;
==Project Description&amp;lt;ref&amp;gt;https://github.com/servo/servo/wiki/CSS-parse-error-reporting&amp;lt;/ref&amp;gt;==&lt;br /&gt;
We will be adding the capability of exposing CSS errors to Servo. We will be using Firefox remote developer tools to inspect and debug the code in Servo.Firefox supports remote developer tools - ie. communicating with an arbitrary server that implements a protocol for exposing information about web content. Servo implements a very basic developer tools server that currently supports executing JS remotely and investigating the DOM tree in the document inspector. The scope of the project is to expand those capabilities by exposing CSS parsing errors.&lt;br /&gt;
===Program Flow===&lt;br /&gt;
*Ensure that Servo can compile and run the given tests. &lt;br /&gt;
*Choose a website that is compatible with Servo and attach the remote developer tools to it. &lt;br /&gt;
'''Initial steps'''&lt;br /&gt;
*Build Servo&lt;br /&gt;
*Attach remote developer tools&lt;br /&gt;
*Making initial changes and build Servo&lt;br /&gt;
*Generate CSS error messages&lt;br /&gt;
*Process error messages and retrieve cached messages&lt;br /&gt;
*Integrate and build again&lt;br /&gt;
'''Subsequent steps'''&lt;br /&gt;
*Generate messages which communicate the errors to the script thread. &lt;br /&gt;
*Process the messages and provide support for caching them and sending them to the devtools server if it exists. &lt;br /&gt;
*Provide the functionality to retrieve the cached CSS error messages whenever requested.&lt;br /&gt;
&lt;br /&gt;
==Environment Setup&amp;lt;ref&amp;gt;https://github.com/servo/servo&amp;lt;/ref&amp;gt;==&lt;br /&gt;
===Pre-requisites===&lt;br /&gt;
On Debian-based Linuxes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install curl freeglut3-dev\&lt;br /&gt;
    libfreetype6-dev libgl1-mesa-dri libglib2.0-dev xorg-dev \&lt;br /&gt;
    gperf g++ cmake python-virtualenv python-pip \&lt;br /&gt;
    libssl-dev libbz2-dev libosmesa6-dev libxmu6 libxmu-dev libglu1-mesa-dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On Fedora:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo dnf install curl freeglut-devel libtool gcc-c++ libXi-devel \&lt;br /&gt;
    freetype-devel mesa-libGL-devel glib2-devel libX11-devel libXrandr-devel gperf \&lt;br /&gt;
    fontconfig-devel cabextract ttmkfdir python python-virtualenv python-pip expat-devel \&lt;br /&gt;
    rpm-build openssl-devel cmake bzip2-devel libXcursor-devel libXmu-devel mesa-libOSMesa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cloning servo===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Building Servo===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Requirement Analysis==&lt;br /&gt;
&lt;br /&gt;
===Steps to be followed as a follow-up of OSS project -===&lt;br /&gt;
&lt;br /&gt;
* make log_css_error in components/style/parser.rs take a &amp;amp;ParserContext argument and call this method&lt;br /&gt;
* extract the existing code from log_css_err into a new type that implements ParseErrorReporter in components/layout/layout_task.rs and pass instances of that type to any code that ends up creating a ParserContext value&lt;br /&gt;
* at this point, Servo should compile and execute almost exactly as before, but where RUST_LOG=style used to expose CSS errors, now RUST_LOG=layout::layout_task will be required instead.&lt;br /&gt;
&lt;br /&gt;
===Steps to be followed specific for final project -===&lt;br /&gt;
&lt;br /&gt;
* Add a PipelineId (from components/msg/constellation_msg.rs) member to ParserContext, to represent the source of parse errors that occur&lt;br /&gt;
* Define a new message type in ConstellationControlMsg which contains all of the information necessary to report a CSS error (including the pipeline ID), and make this new error reporter communicate with the script thread by sending messages over a Sender&amp;lt;ConstellationControlMsg&amp;gt; value that can be obtained from the code in layout_task.rs.&lt;br /&gt;
* Process the new message type in components/script/script_task.rs by -&lt;br /&gt;
  * caching each reported parse error in a vector in Document (components/script/dom/document.rs)&lt;br /&gt;
  * checking the devtools_wants_updates flag and sending it to the devtools server if it exists (see notify_devtools for a model in script_task.rs)&lt;br /&gt;
* Retrieve any cached parse errors for a document on request in handle_get_cached_messages in components/scripts/devtools.rs&lt;br /&gt;
&lt;br /&gt;
===Appurtenant tasks -===&lt;br /&gt;
&lt;br /&gt;
* Since we are working on the main servo build the changes we make to the build usually have a cascading affect in dependent libraries and files. We are also doing the tasks of resolving the issues caused by the dependency. So, the scope of the requirements are larger than those specified above.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mozilla Mozilla]&lt;br /&gt;
* [https://github.com/rust-lang/rust Rust]&lt;br /&gt;
* [https://github.com/servo/servo Servo]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_M1501_Report_CSS_errors_to_the_devtools,_both_stored_and_live&amp;diff=99150</id>
		<title>CSC/ECE 517 Fall 2015 M1501 Report CSS errors to the devtools, both stored and live</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_M1501_Report_CSS_errors_to_the_devtools,_both_stored_and_live&amp;diff=99150"/>
		<updated>2015-11-09T21:07:48Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Added links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Rust_(programming_language) Rust] is a programming language developed by [http://en.wikipedia.org/wiki/Mozilla Mozilla]. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo] is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;br /&gt;
&lt;br /&gt;
==Project Description&amp;lt;ref&amp;gt;https://github.com/servo/servo/wiki/CSS-parse-error-reporting&amp;lt;/ref&amp;gt;==&lt;br /&gt;
We will be adding the capability of exposing CSS errors to Servo. We will be using Firefox remote developer tools to inspect and debug the code in Servo.Firefox supports remote developer tools - ie. communicating with an arbitrary server that implements a protocol for exposing information about web content. Servo implements a very basic developer tools server that currently supports executing JS remotely and investigating the DOM tree in the document inspector. The scope of the project is to expand those capabilities by exposing CSS parsing errors.&lt;br /&gt;
===Program Flow===&lt;br /&gt;
*Ensure that Servo can compile and run the given tests. &lt;br /&gt;
*Choose a website that is compatible with Servo and attach the remote developer tools to it. &lt;br /&gt;
'''Initial steps'''&lt;br /&gt;
*Build Servo&lt;br /&gt;
*Attach remote developer tools&lt;br /&gt;
*Making initial changes and build Servo&lt;br /&gt;
*Generate CSS error messages&lt;br /&gt;
*Process error messages and retrieve cached messages&lt;br /&gt;
*Integrate and build again&lt;br /&gt;
'''Subsequent steps'''&lt;br /&gt;
*Generate messages which communicate the errors to the script thread. &lt;br /&gt;
*Process the messages and provide support for caching them and sending them to the devtools server if it exists. &lt;br /&gt;
*Provide the functionality to retrieve the cached CSS error messages whenever requested.&lt;br /&gt;
&lt;br /&gt;
==Environment Setup&amp;lt;ref&amp;gt;https://github.com/servo/servo&amp;lt;/ref&amp;gt;==&lt;br /&gt;
===Pre-requisites===&lt;br /&gt;
On Debian-based Linuxes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install curl freeglut3-dev\&lt;br /&gt;
    libfreetype6-dev libgl1-mesa-dri libglib2.0-dev xorg-dev \&lt;br /&gt;
    gperf g++ cmake python-virtualenv python-pip \&lt;br /&gt;
    libssl-dev libbz2-dev libosmesa6-dev libxmu6 libxmu-dev libglu1-mesa-dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On Fedora:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo dnf install curl freeglut-devel libtool gcc-c++ libXi-devel \&lt;br /&gt;
    freetype-devel mesa-libGL-devel glib2-devel libX11-devel libXrandr-devel gperf \&lt;br /&gt;
    fontconfig-devel cabextract ttmkfdir python python-virtualenv python-pip expat-devel \&lt;br /&gt;
    rpm-build openssl-devel cmake bzip2-devel libXcursor-devel libXmu-devel mesa-libOSMesa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cloning servo===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Building Servo===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Requirement Analysis==&lt;br /&gt;
&lt;br /&gt;
===Steps to be followed as a follow-up of OSS project -===&lt;br /&gt;
&lt;br /&gt;
* make log_css_error in components/style/parser.rs take a &amp;amp;ParserContext argument and call this method&lt;br /&gt;
* extract the existing code from log_css_err into a new type that implements ParseErrorReporter in components/layout/layout_task.rs and pass instances of that type to any code that ends up creating a ParserContext value&lt;br /&gt;
* at this point, Servo should compile and execute almost exactly as before, but where RUST_LOG=style used to expose CSS errors, now RUST_LOG=layout::layout_task will be required instead.&lt;br /&gt;
&lt;br /&gt;
===Steps to be followed specific for final project -===&lt;br /&gt;
&lt;br /&gt;
* Add a PipelineId (from components/msg/constellation_msg.rs) member to ParserContext, to represent the source of parse errors that occur&lt;br /&gt;
* Define a new message type in ConstellationControlMsg which contains all of the information necessary to report a CSS error (including the pipeline ID), and make this new error reporter communicate with the script thread by sending messages over a Sender&amp;lt;ConstellationControlMsg&amp;gt; value that can be obtained from the code in layout_task.rs.&lt;br /&gt;
* Process the new message type in components/script/script_task.rs by -&lt;br /&gt;
  * caching each reported parse error in a vector in Document (components/script/dom/document.rs)&lt;br /&gt;
  * checking the devtools_wants_updates flag and sending it to the devtools server if it exists (see notify_devtools for a model in script_task.rs)&lt;br /&gt;
* Retrieve any cached parse errors for a document on request in handle_get_cached_messages in components/scripts/devtools.rs&lt;br /&gt;
&lt;br /&gt;
===Appurtenant tasks -===&lt;br /&gt;
&lt;br /&gt;
* Since we are working on the main servo build the changes we make to the build usually have a cascading affect in dependent libraries and files. We are also doing the tasks of resolving the issues caused by the dependency. So, the scope of the requirements are larger than those specified above.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [https://github.com/rust-lang/rust Rust]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_M1501_Report_CSS_errors_to_the_devtools,_both_stored_and_live&amp;diff=99117</id>
		<title>CSC/ECE 517 Fall 2015 M1501 Report CSS errors to the devtools, both stored and live</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_M1501_Report_CSS_errors_to_the_devtools,_both_stored_and_live&amp;diff=99117"/>
		<updated>2015-11-09T20:44:26Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Rust_(programming_language) Rust] is a programming language developed by [http://en.wikipedia.org/wiki/Mozilla Mozilla]. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo] is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;br /&gt;
&lt;br /&gt;
==Project Description&amp;lt;ref&amp;gt;https://github.com/servo/servo/wiki/CSS-parse-error-reporting&amp;lt;/ref&amp;gt;==&lt;br /&gt;
We will be adding the capability of exposing CSS errors to Servo. We will be using Firefox remote developer tools to inspect and debug the code in Servo.Firefox supports remote developer tools - ie. communicating with an arbitrary server that implements a protocol for exposing information about web content. Servo implements a very basic developer tools server that currently supports executing JS remotely and investigating the DOM tree in the document inspector. The scope of the project is to expand those capabilities by exposing CSS parsing errors.&lt;br /&gt;
===Program Flow===&lt;br /&gt;
*Ensure that Servo can compile and run the given tests. &lt;br /&gt;
*Choose a website that is compatible with Servo and attach the remote developer tools to it. &lt;br /&gt;
'''Initial steps'''&lt;br /&gt;
*Build Servo&lt;br /&gt;
*Attach remote developer tools&lt;br /&gt;
*Making initial changes and build Servo&lt;br /&gt;
*Generate CSS error messages&lt;br /&gt;
*Process error messages and retrieve cached messages&lt;br /&gt;
*Integrate and build again&lt;br /&gt;
'''Subsequent steps'''&lt;br /&gt;
*Generate messages which communicate the errors to the script thread. &lt;br /&gt;
*Process the messages and provide support for caching them and sending them to the devtools server if it exists. &lt;br /&gt;
*Provide the functionality to retrieve the cached CSS error messages whenever requested.&lt;br /&gt;
&lt;br /&gt;
==Environment Setup&amp;lt;ref&amp;gt;https://github.com/servo/servo&amp;lt;/ref&amp;gt;==&lt;br /&gt;
===Pre-requisites===&lt;br /&gt;
On Debian-based Linuxes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install curl freeglut3-dev\&lt;br /&gt;
    libfreetype6-dev libgl1-mesa-dri libglib2.0-dev xorg-dev \&lt;br /&gt;
    gperf g++ cmake python-virtualenv python-pip \&lt;br /&gt;
    libssl-dev libbz2-dev libosmesa6-dev libxmu6 libxmu-dev libglu1-mesa-dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On Fedora:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo dnf install curl freeglut-devel libtool gcc-c++ libXi-devel \&lt;br /&gt;
    freetype-devel mesa-libGL-devel glib2-devel libX11-devel libXrandr-devel gperf \&lt;br /&gt;
    fontconfig-devel cabextract ttmkfdir python python-virtualenv python-pip expat-devel \&lt;br /&gt;
    rpm-build openssl-devel cmake bzip2-devel libXcursor-devel libXmu-devel mesa-libOSMesa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cloning servo===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Building Servo===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Requirement Analysis==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_M1501_Report_CSS_errors_to_the_devtools,_both_stored_and_live&amp;diff=99095</id>
		<title>CSC/ECE 517 Fall 2015 M1501 Report CSS errors to the devtools, both stored and live</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_M1501_Report_CSS_errors_to_the_devtools,_both_stored_and_live&amp;diff=99095"/>
		<updated>2015-11-09T20:15:41Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Added and Updated content from my userpage&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Rust_(programming_language) Rust] is a programming language developed by [http://en.wikipedia.org/wiki/Mozilla Mozilla]. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo] is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Requirement Analysis==&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99092</id>
		<title>User:Prdesai2</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99092"/>
		<updated>2015-11-09T20:08:32Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: added headings&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Rust_(programming_language) Rust] is a programming language developed by [http://en.wikipedia.org/wiki/Mozilla Mozilla]. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo] is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Requirement Analysis==&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99087</id>
		<title>User:Prdesai2</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99087"/>
		<updated>2015-11-09T19:27:46Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Updated introduction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Rust_(programming_language) Rust] is a programming language developed by [http://en.wikipedia.org/wiki/Mozilla Mozilla]. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo] is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99086</id>
		<title>User:Prdesai2</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99086"/>
		<updated>2015-11-09T19:25:58Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Updated introduction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Rust_(programming_language) Rust] is a programming language developed by [http://en.wikipedia.org/wiki/Mozilla Mozilla]. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book/README.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo] is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99085</id>
		<title>User:Prdesai2</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99085"/>
		<updated>2015-11-09T19:16:40Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Added references&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
Rust&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Rust_(programming_language)&amp;lt;/ref&amp;gt; is a programming language developed by Mozilla. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book/README.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
Servo&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Servo_(layout_engine)&amp;lt;/ref&amp;gt; is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99084</id>
		<title>User:Prdesai2</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Prdesai2&amp;diff=99084"/>
		<updated>2015-11-09T19:15:49Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Added design document and its introduction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
&lt;br /&gt;
Rust&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Rust_(programming_language)&amp;lt;/ref&amp;gt; is a programming language developed by Mozilla. It is used to design concurrent and safe systems. It is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at: embedding in other languages, programs with specific space and time requirements, and writing low-level code, like device drivers and operating systems. &amp;lt;ref&amp;gt;http://doc.rust-lang.org/nightly/book/README.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
&lt;br /&gt;
Servo&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Servo_(layout_engine)&amp;lt;/ref&amp;gt; is an experimental web browser layout engine. It is developed by Mozilla and written in Rust. It provides an [https://en.wikipedia.org/wiki/Application_programming_interface API] for hosting the engine within other software. The Servo browser currently provides developer tools to inspect [https://en.wikipedia.org/wiki/Document_Object_Model DOM], execute [https://en.wikipedia.org/wiki/JavaScript JavaScript] remotely.&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/oss_E1562_APS&amp;diff=98351</id>
		<title>CSC/ECE 517 Fall 2015/oss E1562 APS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/oss_E1562_APS&amp;diff=98351"/>
		<updated>2015-11-06T16:06:39Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: updated code snippet&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1562. Refactor AssignmentParticipant model'''&amp;lt;ref&amp;gt;Project Description document https://docs.google.com/document/d/1uWs3zyrupTmrOFuv5IbVWCF4NRvCXqJmg8dZ0wCqgus&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page provides a brief description of the '''Expertiza''' project. The project is aimed at refactoring the AssignmentParticipant model which is subclass of Participant model. This model is used to maintain the list of students/users participating in a given assignment. For any new or existing assignments, this model manages the entire list of users assigned to that particular assignment. It primarily includes method for scores calculations, assignment submission paths, reviews, etc. As part of this project, some of the methods have been removed which were not being used anywhere, some have been moved to their appropriate helper module and some have been refactored into smaller ones.&lt;br /&gt;
&lt;br /&gt;
==Introduction to Expertiza==&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system which provides incremental learning from the class. This project has been developed together by faculty and students using [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create, edit and delete assignments, create new assignment topics, assign them to a particular class or selected students, have students work on teams and then review each other's assignments at the end. For the students, they can signup for topics, form teams, and submit their projects and assignments. &lt;br /&gt;
Students then review the work done by other students and give suggestions to improve. Teams after reviews are allotted scores and they can refer to the peer comments to further improve their work. It also supports submission of different file types for assignments, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
==Why refactoring?==&lt;br /&gt;
'''Refactoring'''&amp;lt;ref&amp;gt;Refactoring https://en.wikipedia.org/wiki/Code_refactoring&amp;lt;/ref&amp;gt; is restructuring of code without the need of changing any external behavior. It reduces complexity and improves readability. It also becomes easy to extend the application with respect to different modules and their functionalities.&lt;br /&gt;
Some common techniques to refactor are:&lt;br /&gt;
&lt;br /&gt;
* Moving methods to appropriate modules&lt;br /&gt;
* Breaking methods into more meaningful functionality&lt;br /&gt;
* Creating more generalized code.&lt;br /&gt;
* Renaming methods and variable.&lt;br /&gt;
* Inheritance&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
Refactor '''AssignmentParticipant''' model which is a subclass of '''Participant''' model.&lt;br /&gt;
The following tasks have been performed as per the requirements.&lt;br /&gt;
&lt;br /&gt;
* Refactor scores method to smaller methods.&lt;br /&gt;
* In set_handle method, there is no need for a separate ELSEIF statement. Club the ELSEIF statement into IF statement as an another OR condition.&lt;br /&gt;
* Remove methods like compute_quiz_scores(scores) , average_score_per_assignment(assignment_id) which are not being used.&lt;br /&gt;
* Method cycle_deviation_score(cycle) is also present in CollusionCycle, remove it from this class.&lt;br /&gt;
* Methods related to reviews like teammate_reviews, bookmark_reviews do not belong to AssignmentParticipant model. Move them to the appropriate class.&lt;br /&gt;
* Methods related to files and directories like files(directory) should not be present in AssignmentParticipant model, move them to FileHelper module.&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
===Scores method===&lt;br /&gt;
The method '''scores''' has been converted to smaller methods '''scores''', '''assignment_questionnaires''',  '''merge_scores''', '''calculate_scores'''. It is a good practice to keep the methods not extremely long as they tend to complicate the functionality and the readability.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def scores(questions)&lt;br /&gt;
    scores = {}&lt;br /&gt;
    scores[:participant] = self&lt;br /&gt;
    self.assignment.questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.find_by_assignment_id_and_questionnaire_id(self.assignment.id, questionnaire.id).used_in_round&lt;br /&gt;
      #create symbol for &amp;quot;varying rubrics&amp;quot; feature -Yang&lt;br /&gt;
      if(round!=nil)&lt;br /&gt;
        questionnaire_symbol = (questionnaire.symbol.to_s+round.to_s).to_sym&lt;br /&gt;
      else&lt;br /&gt;
        questionnaire_symbol = questionnaire.symbol&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[questionnaire_symbol] = {}&lt;br /&gt;
&lt;br /&gt;
      if round==nil&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_for(self)&lt;br /&gt;
      else&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_round_for(self,round)&lt;br /&gt;
      end&lt;br /&gt;
      scores[questionnaire_symbol][:scores] = Answer.compute_scores(scores[questionnaire_symbol][:assessments], questions[questionnaire_symbol])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = self.assignment.compute_total_score(scores)&lt;br /&gt;
&lt;br /&gt;
    #merge scores[review#] (for each round) to score[review]  -Yang&lt;br /&gt;
    if self.assignment.varying_rubrics_by_round?&lt;br /&gt;
      review_sym = &amp;quot;review&amp;quot;.to_sym&lt;br /&gt;
      scores[review_sym] = Hash.new&lt;br /&gt;
      scores[review_sym][:assessments] = Array.new&lt;br /&gt;
      scores[review_sym][:scores] = Hash.new&lt;br /&gt;
      scores[review_sym][:scores][:max] = -999999999&lt;br /&gt;
      scores[review_sym][:scores][:min] = 999999999&lt;br /&gt;
      scores[review_sym][:scores][:avg] = 0&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      for i in 1..self.assignment.get_review_rounds&lt;br /&gt;
        round_sym = (&amp;quot;review&amp;quot;+i.to_s).to_sym&lt;br /&gt;
        if scores[round_sym][:assessments].nil? || scores[round_sym][:assessments].length==0&lt;br /&gt;
          next&lt;br /&gt;
        end&lt;br /&gt;
        length_of_assessments=scores[round_sym][:assessments].length.to_f&lt;br /&gt;
&lt;br /&gt;
        scores[review_sym][:assessments]+=scores[round_sym][:assessments]&lt;br /&gt;
&lt;br /&gt;
        if(scores[round_sym][:scores][:max]!=nil &amp;amp;&amp;amp; scores[review_sym][:scores][:max]&amp;lt;scores[round_sym][:scores][:max])&lt;br /&gt;
          scores[review_sym][:scores][:max]= scores[round_sym][:scores][:max]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:min]!= nil &amp;amp;&amp;amp; scores[review_sym][:scores][:min]&amp;gt;scores[round_sym][:scores][:min])&lt;br /&gt;
          scores[review_sym][:scores][:min]= scores[round_sym][:scores][:min]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:avg]!=nil)&lt;br /&gt;
          total_score += scores[round_sym][:scores][:avg]*length_of_assessments&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      if scores[review_sym][:scores][:max] == -999999999 &amp;amp;&amp;amp; scores[review_sym][:scores][:min] == 999999999&lt;br /&gt;
               scores[review_sym][:scores][:max] = 0&lt;br /&gt;
               scores[review_sym][:scores][:min] = 0&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[review_sym][:scores][:avg] = total_score/scores[review_sym][:assessments].length.to_f&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # In the event that this is a microtask, we need to scale the score accordingly and record the total possible points&lt;br /&gt;
    # PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else&lt;br /&gt;
    if assignment.is_microtask?&lt;br /&gt;
      topic = SignUpTopic.find_by_assignment_id(assignment.id)&lt;br /&gt;
      if !topic.nil?&lt;br /&gt;
        scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)&lt;br /&gt;
        scores[:max_pts_available] = topic.micropayment&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # for all quiz questionnaires (quizzes) taken by the participant&lt;br /&gt;
    quiz_responses = Array.new&lt;br /&gt;
    quiz_response_mappings = QuizResponseMap.where(reviewer_id: self.id)&lt;br /&gt;
    quiz_response_mappings.each do |qmapping|&lt;br /&gt;
      if (qmapping.response)&lt;br /&gt;
        quiz_responses &amp;lt;&amp;lt; qmapping.response&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #scores[:quiz] = Hash.new&lt;br /&gt;
    #scores[:quiz][:assessments] = quiz_responses&lt;br /&gt;
    #scores[:quiz][:scores] = Answer.compute_quiz_scores(scores[:quiz][:assessments])&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = assignment.compute_total_score(scores)&lt;br /&gt;
    #scores[:total_score] += compute_quiz_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    # move lots of calculation from view(_participant.html.erb) to model&lt;br /&gt;
    if self.grade&lt;br /&gt;
      scores[:total_score] = self.grade&lt;br /&gt;
    else&lt;br /&gt;
      total_score = scores[:total_score]&lt;br /&gt;
      if total_score &amp;gt; 100&lt;br /&gt;
        total_score = 100&lt;br /&gt;
      end&lt;br /&gt;
      scores[:total_score] = total_score&lt;br /&gt;
    scores&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
||&lt;br /&gt;
* scores(questions) method&lt;br /&gt;
&lt;br /&gt;
  def scores(questions)&lt;br /&gt;
    scores = {}&lt;br /&gt;
    scores[:participant] = self&lt;br /&gt;
&lt;br /&gt;
    assignment_questionnaires(questions, scores)&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = self.assignment.compute_total_score(scores)&lt;br /&gt;
&lt;br /&gt;
    merge_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    # In the event that this is a microtask, we need to scale the score accordingly and record the total possible points&lt;br /&gt;
    # PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else&lt;br /&gt;
    if assignment.is_microtask?&lt;br /&gt;
      topic = SignUpTopic.find_by_assignment_id(assignment.id)&lt;br /&gt;
      if !topic.nil?&lt;br /&gt;
        scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)&lt;br /&gt;
        scores[:max_pts_available] = topic.micropayment&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # for all quiz questionnaires (quizzes) taken by the participant&lt;br /&gt;
    quiz_responses = Array.new&lt;br /&gt;
    quiz_response_mappings = QuizResponseMap.where(reviewer_id: self.id)&lt;br /&gt;
    quiz_response_mappings.each do |qmapping|&lt;br /&gt;
      if (qmapping.response)&lt;br /&gt;
        quiz_responses &amp;lt;&amp;lt; qmapping.response&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #scores[:quiz] = Hash.new&lt;br /&gt;
    #scores[:quiz][:assessments] = quiz_responses&lt;br /&gt;
    #scores[:quiz][:scores] = Answer.compute_quiz_scores(scores[:quiz][:assessments])&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = assignment.compute_total_score(scores)&lt;br /&gt;
    #scores[:total_score] += compute_quiz_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    calculate_scores(scores)&lt;br /&gt;
  end&lt;br /&gt;
* assignment_questionnaires(questions, scores) method&lt;br /&gt;
&lt;br /&gt;
  def assignment_questionnaires(questions, scores)&lt;br /&gt;
    self.assignment.questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.find_by_assignment_id_and_questionnaire_id(self.assignment.id, questionnaire.id).used_in_round&lt;br /&gt;
      #create symbol for &amp;quot;varying rubrics&amp;quot; feature -Yang&lt;br /&gt;
      if(round!=nil)&lt;br /&gt;
        questionnaire_symbol = (questionnaire.symbol.to_s+round.to_s).to_sym&lt;br /&gt;
      else&lt;br /&gt;
        questionnaire_symbol = questionnaire.symbol&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[questionnaire_symbol] = {}&lt;br /&gt;
&lt;br /&gt;
      if round==nil&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_for(self)&lt;br /&gt;
      else&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_round_for(self,round)&lt;br /&gt;
      end&lt;br /&gt;
      scores[questionnaire_symbol][:scores] = Answer.compute_scores(scores[questionnaire_symbol][:assessments], questions[questionnaire_symbol])&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* merge_scores(scores) method&lt;br /&gt;
&lt;br /&gt;
  def merge_scores(scores)&lt;br /&gt;
    #merge scores[review#] (for each round) to score[review]  -Yang&lt;br /&gt;
    if self.assignment.varying_rubrics_by_round?&lt;br /&gt;
      review_sym = &amp;quot;review&amp;quot;.to_sym&lt;br /&gt;
      scores[review_sym] = Hash.new&lt;br /&gt;
      scores[review_sym][:assessments] = Array.new&lt;br /&gt;
      scores[review_sym][:scores] = Hash.new&lt;br /&gt;
      scores[review_sym][:scores][:max] = -999999999&lt;br /&gt;
      scores[review_sym][:scores][:min] = 999999999&lt;br /&gt;
      scores[review_sym][:scores][:avg] = 0&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      for i in 1..self.assignment.get_review_rounds&lt;br /&gt;
        round_sym = (&amp;quot;review&amp;quot;+i.to_s).to_sym&lt;br /&gt;
        if scores[round_sym][:assessments].nil? || scores[round_sym][:assessments].length==0&lt;br /&gt;
          next&lt;br /&gt;
        end&lt;br /&gt;
        length_of_assessments=scores[round_sym][:assessments].length.to_f&lt;br /&gt;
&lt;br /&gt;
        scores[review_sym][:assessments]+=scores[round_sym][:assessments]&lt;br /&gt;
&lt;br /&gt;
        if(scores[round_sym][:scores][:max]!=nil &amp;amp;&amp;amp; scores[review_sym][:scores][:max]&amp;lt;scores[round_sym][:scores][:max])&lt;br /&gt;
          scores[review_sym][:scores][:max]= scores[round_sym][:scores][:max]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:min]!= nil &amp;amp;&amp;amp; scores[review_sym][:scores][:min]&amp;gt;scores[round_sym][:scores][:min])&lt;br /&gt;
          scores[review_sym][:scores][:min]= scores[round_sym][:scores][:min]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:avg]!=nil)&lt;br /&gt;
          total_score += scores[round_sym][:scores][:avg]*length_of_assessments&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      if scores[review_sym][:scores][:max] == -999999999 &amp;amp;&amp;amp; scores[review_sym][:scores][:min] == 999999999&lt;br /&gt;
        scores[review_sym][:scores][:max] = 0&lt;br /&gt;
        scores[review_sym][:scores][:min] = 0&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[review_sym][:scores][:avg] = total_score/scores[review_sym][:assessments].length.to_f&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* calculate_scores(scores) method&lt;br /&gt;
&lt;br /&gt;
  def calculate_scores(scores)&lt;br /&gt;
    # move lots of calculation from view(_participant.html.erb) to model&lt;br /&gt;
    if self.grade&lt;br /&gt;
      scores[:total_score] = self.grade&lt;br /&gt;
    else&lt;br /&gt;
      total_score = scores[:total_score]&lt;br /&gt;
      if total_score &amp;gt; 100&lt;br /&gt;
        total_score = 100&lt;br /&gt;
      end&lt;br /&gt;
      scores[:total_score] = total_score&lt;br /&gt;
      scores&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===set_handle method===&lt;br /&gt;
The set_handle method had an unncessary ELSIF statement which was performing the same action '''self.handle = self.user.name'''. This has been clubbed as an OR condition to the IF statement and the first ELSIF statement has been removed.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def set_handle&lt;br /&gt;
      if self.user.handle == nil or self.user.handle == &amp;quot;&amp;quot;&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      elsif AssignmentParticipant.where(parent_id: self.assignment.id, handle: self.user.handle).length &amp;gt; 0&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      else&lt;br /&gt;
        self.handle = self.user.handle&lt;br /&gt;
      end&lt;br /&gt;
      self.save!&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
||def set_handle&lt;br /&gt;
      if self.user.handle == nil or self.user.handle == &amp;quot;&amp;quot; or AssignmentParticipant.where(parent_id: self.assignment.id, handle: self.user.handle).length &amp;gt; 0&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      else&lt;br /&gt;
        self.handle = self.user.handle&lt;br /&gt;
      end&lt;br /&gt;
      self.save!&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===File and directory methods===&lt;br /&gt;
The files and directory methods from AssignmentParticipant model have been moved to the '''FileHelper''' module.&lt;br /&gt;
The methods '''files''', '''submitted_files''' and '''dir_path''' are appropriate for the '''FileHelper' module and hence been moved there.&lt;br /&gt;
The below line was added to the AssignmentParticipant model.&lt;br /&gt;
include FileHelper&lt;br /&gt;
&lt;br /&gt;
The AssignmentParticipant class would look like&lt;br /&gt;
  class AssignmentParticipant &amp;lt; Participant&lt;br /&gt;
    require 'wiki_helper'&lt;br /&gt;
    '''include FileHelper'''&lt;br /&gt;
Methods moved to FileHelper:&lt;br /&gt;
&lt;br /&gt;
* submitted_files&lt;br /&gt;
&lt;br /&gt;
  def submitted_files&lt;br /&gt;
    files(self.path) if self.directory_num&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* files(directory)&lt;br /&gt;
&lt;br /&gt;
  def files(directory)&lt;br /&gt;
    files_list = Dir[directory + &amp;quot;/*&amp;quot;]&lt;br /&gt;
    files = Array.new&lt;br /&gt;
&lt;br /&gt;
    files_list.each do |file|&lt;br /&gt;
      if File.directory?(file)&lt;br /&gt;
        dir_files = files(file)&lt;br /&gt;
        dir_files.each{|f| files &amp;lt;&amp;lt; f}&lt;br /&gt;
      end&lt;br /&gt;
      files &amp;lt;&amp;lt; file&lt;br /&gt;
    end&lt;br /&gt;
    files&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* submitted_files()&lt;br /&gt;
&lt;br /&gt;
  def submitted_files()&lt;br /&gt;
    files = Array.new&lt;br /&gt;
    if(self.directory_num)&lt;br /&gt;
      files = files(self.path)&lt;br /&gt;
    end&lt;br /&gt;
    return files&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* dir_path&lt;br /&gt;
&lt;br /&gt;
  def dir_path&lt;br /&gt;
    assignment.try :directory_path&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Remove unused methods===&lt;br /&gt;
The following methods have been removed as they were not being used by the application.&lt;br /&gt;
&lt;br /&gt;
'''def average_score_per_assignment(assignment_id)'''&lt;br /&gt;
&lt;br /&gt;
 def average_score_per_assignment(assignment_id)&lt;br /&gt;
    return 0 if self.response_maps.size == 0&lt;br /&gt;
&lt;br /&gt;
    sum_of_scores = 0&lt;br /&gt;
&lt;br /&gt;
    self.response_maps.metareview_response_maps.each do |metaresponse_map|&lt;br /&gt;
      if !metaresponse_map.response.empty? &amp;amp;&amp;amp; response_map == assignment_id then&lt;br /&gt;
        sum_of_scores = sum_of_scores + response_map.response.last.average_score&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    (sum_of_scores / self.response_maps.size).to_i&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def quiz_taken_by?(contributor, reviewer)'''&lt;br /&gt;
&lt;br /&gt;
  def quiz_taken_by?(contributor, reviewer)&lt;br /&gt;
    quiz_id = QuizQuestionnaire.find_by_instructor_id(contributor.id)&lt;br /&gt;
    return QuizResponseMap.where(['reviewee_id = ? AND reviewer_id = ? AND reviewed_object_id = ?',&lt;br /&gt;
                                  self.id, reviewer.id, quiz_id]).count &amp;gt; 0&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def has_quiz?'''&lt;br /&gt;
&lt;br /&gt;
  def has_quiz?&lt;br /&gt;
    return !QuizQuestionnaire.find_by_instructor_id(self.id).nil?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def reviewees'''&lt;br /&gt;
&lt;br /&gt;
  def reviewees&lt;br /&gt;
    reviewees = []&lt;br /&gt;
    rmaps = ResponseMap.all(conditions: [&amp;quot;reviewer_id = #{self.id} &amp;amp;&amp;amp; type = 'ReviewResponseMap'&amp;quot;])&lt;br /&gt;
        rmaps.each { |rm| reviewees.concat(AssignmentTeam.find(rm.reviewee_id).participants) }&lt;br /&gt;
&lt;br /&gt;
    reviewees&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def two_node_cycles'''&lt;br /&gt;
 &lt;br /&gt;
  def two_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap|&lt;br /&gt;
      if ap.reviewers.include?(self)&lt;br /&gt;
        self.reviews_by_reviewer(ap).nil? ? next : s01 = self.reviews_by_reviewer(ap).get_total_score&lt;br /&gt;
        ap.reviews_by_reviewer(self).nil? ? next : s10 = ap.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
        cycles.push([[self, s01], [ap, s10]])&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def three_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
  def three_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap1|&lt;br /&gt;
      ap1.reviewers.each do |ap2|&lt;br /&gt;
        if ap2.reviewers.include?(self)&lt;br /&gt;
          self.reviews_by_reviewer(ap1).nil? ? next : s01 = self.reviews_by_reviewer(ap1).get_total_score&lt;br /&gt;
          ap1.reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.reviews_by_reviewer(ap2).get_total_score&lt;br /&gt;
          ap2.reviews_by_reviewer(self).nil? ? next : s20 = ap2.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
          cycles.push([[self, s01], [ap1, s12], [ap2, s20]])&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def four_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
  def four_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap1|&lt;br /&gt;
      ap1.reviewers.each do |ap2|&lt;br /&gt;
        ap2.reviewers.each do |ap3|&lt;br /&gt;
          if ap3.reviewers.include?(self)&lt;br /&gt;
            self.reviews_by_reviewer(ap1).nil? ? next : s01 = self.reviews_by_reviewer(ap1).get_total_score&lt;br /&gt;
            ap1.reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.reviews_by_reviewer(ap2).get_total_score&lt;br /&gt;
            ap2.reviews_by_reviewer(ap3).nil? ? next : s23 = ap2.reviews_by_reviewer(ap3).get_total_score&lt;br /&gt;
            ap3.reviews_by_reviewer(self).nil? ? next : s30 = ap3.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
            cycles.push([[self, s01], [ap1, s12], [ap2, s23], [ap3, s30]])&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def cycle_similarity_score(cycle)'''&lt;br /&gt;
&lt;br /&gt;
  def cycle_similarity_score(cycle)&lt;br /&gt;
    similarity_score = 0.0&lt;br /&gt;
    count = 0.0&lt;br /&gt;
&lt;br /&gt;
    0 ... cycle.size-1.each do |pivot|&lt;br /&gt;
      pivot_score = cycle[pivot][1]&lt;br /&gt;
      similarity_score = similarity_score + (pivot_score - cycle[other][1]).abs&lt;br /&gt;
      count = count + 1.0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    similarity_score = similarity_score / count unless count == 0.0&lt;br /&gt;
    similarity_score&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def cycle_deviation_score(cycle)'''&lt;br /&gt;
&lt;br /&gt;
  def cycle_deviation_score(cycle)&lt;br /&gt;
    deviation_score = 0.0&lt;br /&gt;
    count = 0.0&lt;br /&gt;
&lt;br /&gt;
    0 ... cycle.size.each do |member|&lt;br /&gt;
      participant = AssignmentParticipant.find(cycle[member][0].id)&lt;br /&gt;
      total_score = participant.get_review_score&lt;br /&gt;
      deviation_score = deviation_score + (total_score - cycle[member][1]).abs&lt;br /&gt;
      count = count + 1.0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    deviation_score = deviation_score / count unless count == 0.0&lt;br /&gt;
    deviation_score&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def compute_quiz_scores(scores)'''&lt;br /&gt;
&lt;br /&gt;
  def compute_quiz_scores(scores)&lt;br /&gt;
    total = 0&lt;br /&gt;
    if scores[:quiz][:scores][:avg]&lt;br /&gt;
      return scores[:quiz][:scores][:avg] * 100  / 100.to_f&lt;br /&gt;
    else&lt;br /&gt;
      return 0&lt;br /&gt;
    end&lt;br /&gt;
    return total&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def review_response_maps'''&lt;br /&gt;
&lt;br /&gt;
  def review_response_maps&lt;br /&gt;
      participant = Participant.find(id)&lt;br /&gt;
      team_id = TeamsUser.team_id(participant.parent_id, participant.user_id)&lt;br /&gt;
      ReviewResponseMap.where(reviewee_id: team_id, reviewed_object_id: assignment.id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def members'''&lt;br /&gt;
&lt;br /&gt;
  def members&lt;br /&gt;
    team.try :participants&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def get_hash(time_stamp)'''&lt;br /&gt;
&lt;br /&gt;
  def get_hash(time_stamp)&lt;br /&gt;
    # first generate a hash from the assignment name itself&lt;br /&gt;
    hash_data = Digest::SHA1.digest(self.assignment.name.to_s)&lt;br /&gt;
&lt;br /&gt;
    # second generate a hash from the first hash plus the user name and time stamp&lt;br /&gt;
    sign = hash_data + self.user.name.to_s + time_stamp.strftime(&amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;)&lt;br /&gt;
    Digest::SHA1.digest(sign)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Review methods===&lt;br /&gt;
* The bookmark_reviews() method from AssignmentParticipant was being called once in '''get_assessments_for''' method of '''BookmarkRatingQuestionnaire''' class. It has been replaced by the method statement directly since it only had a single line of code.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def bookmark_reviews&lt;br /&gt;
    BookmarkRatingResponseMap.get_assessments_for(self)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
||def get_assessments_for(participant)&lt;br /&gt;
    BookmarkRatingResponseMap.get_assessments_for(participant) # participant.bookmark_reviews()&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* The teammate_reviews() method from AssignmentParticipant was being called once in '''get_assessments_for''' method of '''TeammateReviewQuestionnaire''' class. It has been replaced by the method statement directly since it only had a single line of code.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def teammate_reviews&lt;br /&gt;
    TeammateReviewResponseMap.get_assessments_for(self)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
||def get_assessments_for(participant)&lt;br /&gt;
    TeammateReviewResponseMap.get_assessments_for(participant)   #participant.teammate_reviews()&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
Please follow the below instruction to test UI:&lt;br /&gt;
* Login to Expertiza on http://152.46.20.199:3000/.&lt;br /&gt;
* Enter username as 'student13' and password as 'password'.&lt;br /&gt;
* You can select a previous assignment 'shivam test' or 'Pankti test'.&lt;br /&gt;
* You should be able to access the pages further&lt;br /&gt;
** Your team- The page content should be visible without any errors.&lt;br /&gt;
** Your work - The upload button for submission should be visible.&lt;br /&gt;
** Your scores- The page should give result 0 and not any error.&lt;br /&gt;
&lt;br /&gt;
When the user runs the application, the behavior of the application remains the same. &lt;br /&gt;
&lt;br /&gt;
The existing [https://en.wikipedia.org/wiki/RSpec RSpec] test cases remain successful. The same can be checked by running&lt;br /&gt;
Rspec spec&lt;br /&gt;
The participant is able to log in to the system, view the assignments, submit links and files in assignment submission, view the scores, review peers, etc. Below are some of the execution screenshots after the refactoring of the model.&lt;br /&gt;
&lt;br /&gt;
The Expertiza Login Screen&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaLoginScreen.jpg]]&lt;br /&gt;
&lt;br /&gt;
User can see all the assignments as below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS2.jpg]]&lt;br /&gt;
&lt;br /&gt;
View team members for the assignment selected. In this case, we have taken a dummy assignment we created.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS3.jpg]]&lt;br /&gt;
&lt;br /&gt;
View the submission page to upload the assignment.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS4.jpg]]&lt;br /&gt;
&lt;br /&gt;
View the scores of an assignment.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS5.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Resources==&lt;br /&gt;
* Expertiza Github repository&amp;lt;ref&amp;gt;Expertiza Github repository https://github.com/expertiza/expertiza&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Our Github repository&amp;lt;ref&amp;gt;Our Github Repository https://github.com/shivamgulati1991/expertiza]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/oss_E1562_APS&amp;diff=98344</id>
		<title>CSC/ECE 517 Fall 2015/oss E1562 APS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/oss_E1562_APS&amp;diff=98344"/>
		<updated>2015-11-06T16:03:58Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Formatted code snippets with before and after block&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1562. Refactor AssignmentParticipant model'''&amp;lt;ref&amp;gt;Project Description document https://docs.google.com/document/d/1uWs3zyrupTmrOFuv5IbVWCF4NRvCXqJmg8dZ0wCqgus&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page provides a brief description of the '''Expertiza''' project. The project is aimed at refactoring the AssignmentParticipant model which is subclass of Participant model. This model is used to maintain the list of students/users participating in a given assignment. For any new or existing assignments, this model manages the entire list of users assigned to that particular assignment. It primarily includes method for scores calculations, assignment submission paths, reviews, etc. As part of this project, some of the methods have been removed which were not being used anywhere, some have been moved to their appropriate helper module and some have been refactored into smaller ones.&lt;br /&gt;
&lt;br /&gt;
==Introduction to Expertiza==&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system which provides incremental learning from the class. This project has been developed together by faculty and students using [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create, edit and delete assignments, create new assignment topics, assign them to a particular class or selected students, have students work on teams and then review each other's assignments at the end. For the students, they can signup for topics, form teams, and submit their projects and assignments. &lt;br /&gt;
Students then review the work done by other students and give suggestions to improve. Teams after reviews are allotted scores and they can refer to the peer comments to further improve their work. It also supports submission of different file types for assignments, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
==Why refactoring?==&lt;br /&gt;
'''Refactoring'''&amp;lt;ref&amp;gt;Refactoring https://en.wikipedia.org/wiki/Code_refactoring&amp;lt;/ref&amp;gt; is restructuring of code without the need of changing any external behavior. It reduces complexity and improves readability. It also becomes easy to extend the application with respect to different modules and their functionalities.&lt;br /&gt;
Some common techniques to refactor are:&lt;br /&gt;
&lt;br /&gt;
* Moving methods to appropriate modules&lt;br /&gt;
* Breaking methods into more meaningful functionality&lt;br /&gt;
* Creating more generalized code.&lt;br /&gt;
* Renaming methods and variable.&lt;br /&gt;
* Inheritance&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
Refactor '''AssignmentParticipant''' model which is a subclass of '''Participant''' model.&lt;br /&gt;
The following tasks have been performed as per the requirements.&lt;br /&gt;
&lt;br /&gt;
* Refactor scores method to smaller methods.&lt;br /&gt;
* In set_handle method, there is no need for a separate ELSEIF statement. Club the ELSEIF statement into IF statement as an another OR condition.&lt;br /&gt;
* Remove methods like compute_quiz_scores(scores) , average_score_per_assignment(assignment_id) which are not being used.&lt;br /&gt;
* Method cycle_deviation_score(cycle) is also present in CollusionCycle, remove it from this class.&lt;br /&gt;
* Methods related to reviews like teammate_reviews, bookmark_reviews do not belong to AssignmentParticipant model. Move them to the appropriate class.&lt;br /&gt;
* Methods related to files and directories like files(directory) should not be present in AssignmentParticipant model, move them to FileHelper module.&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
===Scores method===&lt;br /&gt;
The method '''scores''' has been converted to smaller methods '''scores''', '''assignment_questionnaires''',  '''merge_scores''', '''calculate_scores'''. It is a good practice to keep the methods not extremely long as they tend to complicate the functionality and the readability.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def scores(questions)&lt;br /&gt;
    scores = {}&lt;br /&gt;
    scores[:participant] = self&lt;br /&gt;
    self.assignment.questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.find_by_assignment_id_and_questionnaire_id(self.assignment.id, questionnaire.id).used_in_round&lt;br /&gt;
      #create symbol for &amp;quot;varying rubrics&amp;quot; feature -Yang&lt;br /&gt;
      if(round!=nil)&lt;br /&gt;
        questionnaire_symbol = (questionnaire.symbol.to_s+round.to_s).to_sym&lt;br /&gt;
      else&lt;br /&gt;
        questionnaire_symbol = questionnaire.symbol&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[questionnaire_symbol] = {}&lt;br /&gt;
&lt;br /&gt;
      if round==nil&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_for(self)&lt;br /&gt;
      else&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_round_for(self,round)&lt;br /&gt;
      end&lt;br /&gt;
      scores[questionnaire_symbol][:scores] = Answer.compute_scores(scores[questionnaire_symbol][:assessments], questions[questionnaire_symbol])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = self.assignment.compute_total_score(scores)&lt;br /&gt;
&lt;br /&gt;
    #merge scores[review#] (for each round) to score[review]  -Yang&lt;br /&gt;
    if self.assignment.varying_rubrics_by_round?&lt;br /&gt;
      review_sym = &amp;quot;review&amp;quot;.to_sym&lt;br /&gt;
      scores[review_sym] = Hash.new&lt;br /&gt;
      scores[review_sym][:assessments] = Array.new&lt;br /&gt;
      scores[review_sym][:scores] = Hash.new&lt;br /&gt;
      scores[review_sym][:scores][:max] = -999999999&lt;br /&gt;
      scores[review_sym][:scores][:min] = 999999999&lt;br /&gt;
      scores[review_sym][:scores][:avg] = 0&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      for i in 1..self.assignment.get_review_rounds&lt;br /&gt;
        round_sym = (&amp;quot;review&amp;quot;+i.to_s).to_sym&lt;br /&gt;
        if scores[round_sym][:assessments].nil? || scores[round_sym][:assessments].length==0&lt;br /&gt;
          next&lt;br /&gt;
        end&lt;br /&gt;
        length_of_assessments=scores[round_sym][:assessments].length.to_f&lt;br /&gt;
&lt;br /&gt;
        scores[review_sym][:assessments]+=scores[round_sym][:assessments]&lt;br /&gt;
&lt;br /&gt;
        if(scores[round_sym][:scores][:max]!=nil &amp;amp;&amp;amp; scores[review_sym][:scores][:max]&amp;lt;scores[round_sym][:scores][:max])&lt;br /&gt;
          scores[review_sym][:scores][:max]= scores[round_sym][:scores][:max]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:min]!= nil &amp;amp;&amp;amp; scores[review_sym][:scores][:min]&amp;gt;scores[round_sym][:scores][:min])&lt;br /&gt;
          scores[review_sym][:scores][:min]= scores[round_sym][:scores][:min]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:avg]!=nil)&lt;br /&gt;
          total_score += scores[round_sym][:scores][:avg]*length_of_assessments&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      if scores[review_sym][:scores][:max] == -999999999 &amp;amp;&amp;amp; scores[review_sym][:scores][:min] == 999999999&lt;br /&gt;
               scores[review_sym][:scores][:max] = 0&lt;br /&gt;
               scores[review_sym][:scores][:min] = 0&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[review_sym][:scores][:avg] = total_score/scores[review_sym][:assessments].length.to_f&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # In the event that this is a microtask, we need to scale the score accordingly and record the total possible points&lt;br /&gt;
    # PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else&lt;br /&gt;
    if assignment.is_microtask?&lt;br /&gt;
      topic = SignUpTopic.find_by_assignment_id(assignment.id)&lt;br /&gt;
      if !topic.nil?&lt;br /&gt;
        scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)&lt;br /&gt;
        scores[:max_pts_available] = topic.micropayment&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # for all quiz questionnaires (quizzes) taken by the participant&lt;br /&gt;
    quiz_responses = Array.new&lt;br /&gt;
    quiz_response_mappings = QuizResponseMap.where(reviewer_id: self.id)&lt;br /&gt;
    quiz_response_mappings.each do |qmapping|&lt;br /&gt;
      if (qmapping.response)&lt;br /&gt;
        quiz_responses &amp;lt;&amp;lt; qmapping.response&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #scores[:quiz] = Hash.new&lt;br /&gt;
    #scores[:quiz][:assessments] = quiz_responses&lt;br /&gt;
    #scores[:quiz][:scores] = Answer.compute_quiz_scores(scores[:quiz][:assessments])&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = assignment.compute_total_score(scores)&lt;br /&gt;
    #scores[:total_score] += compute_quiz_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    # move lots of calculation from view(_participant.html.erb) to model&lt;br /&gt;
    if self.grade&lt;br /&gt;
      scores[:total_score] = self.grade&lt;br /&gt;
    else&lt;br /&gt;
      total_score = scores[:total_score]&lt;br /&gt;
      if total_score &amp;gt; 100&lt;br /&gt;
        total_score = 100&lt;br /&gt;
      end&lt;br /&gt;
      scores[:total_score] = total_score&lt;br /&gt;
    scores&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
||&lt;br /&gt;
* scores(questions) method&lt;br /&gt;
&lt;br /&gt;
  def scores(questions)&lt;br /&gt;
    scores = {}&lt;br /&gt;
    scores[:participant] = self&lt;br /&gt;
&lt;br /&gt;
    assignment_questionnaires(questions, scores)&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = self.assignment.compute_total_score(scores)&lt;br /&gt;
&lt;br /&gt;
    merge_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    # In the event that this is a microtask, we need to scale the score accordingly and record the total possible points&lt;br /&gt;
    # PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else&lt;br /&gt;
    if assignment.is_microtask?&lt;br /&gt;
      topic = SignUpTopic.find_by_assignment_id(assignment.id)&lt;br /&gt;
      if !topic.nil?&lt;br /&gt;
        scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)&lt;br /&gt;
        scores[:max_pts_available] = topic.micropayment&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # for all quiz questionnaires (quizzes) taken by the participant&lt;br /&gt;
    quiz_responses = Array.new&lt;br /&gt;
    quiz_response_mappings = QuizResponseMap.where(reviewer_id: self.id)&lt;br /&gt;
    quiz_response_mappings.each do |qmapping|&lt;br /&gt;
      if (qmapping.response)&lt;br /&gt;
        quiz_responses &amp;lt;&amp;lt; qmapping.response&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #scores[:quiz] = Hash.new&lt;br /&gt;
    #scores[:quiz][:assessments] = quiz_responses&lt;br /&gt;
    #scores[:quiz][:scores] = Answer.compute_quiz_scores(scores[:quiz][:assessments])&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = assignment.compute_total_score(scores)&lt;br /&gt;
    #scores[:total_score] += compute_quiz_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    calculate_scores(scores)&lt;br /&gt;
  end&lt;br /&gt;
* assignment_questionnaires(questions, scores) method&lt;br /&gt;
&lt;br /&gt;
  def assignment_questionnaires(questions, scores)&lt;br /&gt;
    self.assignment.questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.find_by_assignment_id_and_questionnaire_id(self.assignment.id, questionnaire.id).used_in_round&lt;br /&gt;
      #create symbol for &amp;quot;varying rubrics&amp;quot; feature -Yang&lt;br /&gt;
      if(round!=nil)&lt;br /&gt;
        questionnaire_symbol = (questionnaire.symbol.to_s+round.to_s).to_sym&lt;br /&gt;
      else&lt;br /&gt;
        questionnaire_symbol = questionnaire.symbol&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[questionnaire_symbol] = {}&lt;br /&gt;
&lt;br /&gt;
      if round==nil&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_for(self)&lt;br /&gt;
      else&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_round_for(self,round)&lt;br /&gt;
      end&lt;br /&gt;
      scores[questionnaire_symbol][:scores] = Answer.compute_scores(scores[questionnaire_symbol][:assessments], questions[questionnaire_symbol])&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* merge_scores(scores) method&lt;br /&gt;
&lt;br /&gt;
  def merge_scores(scores)&lt;br /&gt;
    #merge scores[review#] (for each round) to score[review]  -Yang&lt;br /&gt;
    if self.assignment.varying_rubrics_by_round?&lt;br /&gt;
      review_sym = &amp;quot;review&amp;quot;.to_sym&lt;br /&gt;
      scores[review_sym] = Hash.new&lt;br /&gt;
      scores[review_sym][:assessments] = Array.new&lt;br /&gt;
      scores[review_sym][:scores] = Hash.new&lt;br /&gt;
      scores[review_sym][:scores][:max] = -999999999&lt;br /&gt;
      scores[review_sym][:scores][:min] = 999999999&lt;br /&gt;
      scores[review_sym][:scores][:avg] = 0&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      for i in 1..self.assignment.get_review_rounds&lt;br /&gt;
        round_sym = (&amp;quot;review&amp;quot;+i.to_s).to_sym&lt;br /&gt;
        if scores[round_sym][:assessments].nil? || scores[round_sym][:assessments].length==0&lt;br /&gt;
          next&lt;br /&gt;
        end&lt;br /&gt;
        length_of_assessments=scores[round_sym][:assessments].length.to_f&lt;br /&gt;
&lt;br /&gt;
        scores[review_sym][:assessments]+=scores[round_sym][:assessments]&lt;br /&gt;
&lt;br /&gt;
        if(scores[round_sym][:scores][:max]!=nil &amp;amp;&amp;amp; scores[review_sym][:scores][:max]&amp;lt;scores[round_sym][:scores][:max])&lt;br /&gt;
          scores[review_sym][:scores][:max]= scores[round_sym][:scores][:max]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:min]!= nil &amp;amp;&amp;amp; scores[review_sym][:scores][:min]&amp;gt;scores[round_sym][:scores][:min])&lt;br /&gt;
          scores[review_sym][:scores][:min]= scores[round_sym][:scores][:min]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:avg]!=nil)&lt;br /&gt;
          total_score += scores[round_sym][:scores][:avg]*length_of_assessments&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      if scores[review_sym][:scores][:max] == -999999999 &amp;amp;&amp;amp; scores[review_sym][:scores][:min] == 999999999&lt;br /&gt;
        scores[review_sym][:scores][:max] = 0&lt;br /&gt;
        scores[review_sym][:scores][:min] = 0&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[review_sym][:scores][:avg] = total_score/scores[review_sym][:assessments].length.to_f&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* calculate_scores(scores) method&lt;br /&gt;
&lt;br /&gt;
  def calculate_scores(scores)&lt;br /&gt;
    # move lots of calculation from view(_participant.html.erb) to model&lt;br /&gt;
    if self.grade&lt;br /&gt;
      scores[:total_score] = self.grade&lt;br /&gt;
    else&lt;br /&gt;
      total_score = scores[:total_score]&lt;br /&gt;
      if total_score &amp;gt; 100&lt;br /&gt;
        total_score = 100&lt;br /&gt;
      end&lt;br /&gt;
      scores[:total_score] = total_score&lt;br /&gt;
      scores&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===set_handle method===&lt;br /&gt;
The set_handle method had an unncessary ELSIF statement which was performing the same action '''self.handle = self.user.name'''. This has been clubbed as an OR condition to the IF statement and the first ELSIF statement has been removed.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def set_handle&lt;br /&gt;
      if self.user.handle == nil or self.user.handle == &amp;quot;&amp;quot;&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      elsif AssignmentParticipant.where(parent_id: self.assignment.id, handle: self.user.handle).length &amp;gt; 0&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      else&lt;br /&gt;
        self.handle = self.user.handle&lt;br /&gt;
      end&lt;br /&gt;
      self.save!&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
||&lt;br /&gt;
&lt;br /&gt;
  def set_handle&lt;br /&gt;
      if self.user.handle == nil or self.user.handle == &amp;quot;&amp;quot; or AssignmentParticipant.where(parent_id: self.assignment.id, handle: self.user.handle).length &amp;gt; 0&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      else&lt;br /&gt;
        self.handle = self.user.handle&lt;br /&gt;
      end&lt;br /&gt;
      self.save!&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===File and directory methods===&lt;br /&gt;
The files and directory methods from AssignmentParticipant model have been moved to the '''FileHelper''' module.&lt;br /&gt;
The methods '''files''', '''submitted_files''' and '''dir_path''' are appropriate for the '''FileHelper' module and hence been moved there.&lt;br /&gt;
The below line was added to the AssignmentParticipant model.&lt;br /&gt;
include FileHelper&lt;br /&gt;
&lt;br /&gt;
The AssignmentParticipant class would look like&lt;br /&gt;
  class AssignmentParticipant &amp;lt; Participant&lt;br /&gt;
    require 'wiki_helper'&lt;br /&gt;
    '''include FileHelper'''&lt;br /&gt;
Methods moved to FileHelper:&lt;br /&gt;
&lt;br /&gt;
* submitted_files&lt;br /&gt;
&lt;br /&gt;
  def submitted_files&lt;br /&gt;
    files(self.path) if self.directory_num&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* files(directory)&lt;br /&gt;
&lt;br /&gt;
  def files(directory)&lt;br /&gt;
    files_list = Dir[directory + &amp;quot;/*&amp;quot;]&lt;br /&gt;
    files = Array.new&lt;br /&gt;
&lt;br /&gt;
    files_list.each do |file|&lt;br /&gt;
      if File.directory?(file)&lt;br /&gt;
        dir_files = files(file)&lt;br /&gt;
        dir_files.each{|f| files &amp;lt;&amp;lt; f}&lt;br /&gt;
      end&lt;br /&gt;
      files &amp;lt;&amp;lt; file&lt;br /&gt;
    end&lt;br /&gt;
    files&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* submitted_files()&lt;br /&gt;
&lt;br /&gt;
  def submitted_files()&lt;br /&gt;
    files = Array.new&lt;br /&gt;
    if(self.directory_num)&lt;br /&gt;
      files = files(self.path)&lt;br /&gt;
    end&lt;br /&gt;
    return files&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* dir_path&lt;br /&gt;
&lt;br /&gt;
  def dir_path&lt;br /&gt;
    assignment.try :directory_path&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Remove unused methods===&lt;br /&gt;
The following methods have been removed as they were not being used by the application.&lt;br /&gt;
&lt;br /&gt;
'''def average_score_per_assignment(assignment_id)'''&lt;br /&gt;
&lt;br /&gt;
 def average_score_per_assignment(assignment_id)&lt;br /&gt;
    return 0 if self.response_maps.size == 0&lt;br /&gt;
&lt;br /&gt;
    sum_of_scores = 0&lt;br /&gt;
&lt;br /&gt;
    self.response_maps.metareview_response_maps.each do |metaresponse_map|&lt;br /&gt;
      if !metaresponse_map.response.empty? &amp;amp;&amp;amp; response_map == assignment_id then&lt;br /&gt;
        sum_of_scores = sum_of_scores + response_map.response.last.average_score&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    (sum_of_scores / self.response_maps.size).to_i&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def quiz_taken_by?(contributor, reviewer)'''&lt;br /&gt;
&lt;br /&gt;
  def quiz_taken_by?(contributor, reviewer)&lt;br /&gt;
    quiz_id = QuizQuestionnaire.find_by_instructor_id(contributor.id)&lt;br /&gt;
    return QuizResponseMap.where(['reviewee_id = ? AND reviewer_id = ? AND reviewed_object_id = ?',&lt;br /&gt;
                                  self.id, reviewer.id, quiz_id]).count &amp;gt; 0&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def has_quiz?'''&lt;br /&gt;
&lt;br /&gt;
  def has_quiz?&lt;br /&gt;
    return !QuizQuestionnaire.find_by_instructor_id(self.id).nil?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def reviewees'''&lt;br /&gt;
&lt;br /&gt;
  def reviewees&lt;br /&gt;
    reviewees = []&lt;br /&gt;
    rmaps = ResponseMap.all(conditions: [&amp;quot;reviewer_id = #{self.id} &amp;amp;&amp;amp; type = 'ReviewResponseMap'&amp;quot;])&lt;br /&gt;
        rmaps.each { |rm| reviewees.concat(AssignmentTeam.find(rm.reviewee_id).participants) }&lt;br /&gt;
&lt;br /&gt;
    reviewees&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def two_node_cycles'''&lt;br /&gt;
 &lt;br /&gt;
  def two_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap|&lt;br /&gt;
      if ap.reviewers.include?(self)&lt;br /&gt;
        self.reviews_by_reviewer(ap).nil? ? next : s01 = self.reviews_by_reviewer(ap).get_total_score&lt;br /&gt;
        ap.reviews_by_reviewer(self).nil? ? next : s10 = ap.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
        cycles.push([[self, s01], [ap, s10]])&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def three_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
  def three_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap1|&lt;br /&gt;
      ap1.reviewers.each do |ap2|&lt;br /&gt;
        if ap2.reviewers.include?(self)&lt;br /&gt;
          self.reviews_by_reviewer(ap1).nil? ? next : s01 = self.reviews_by_reviewer(ap1).get_total_score&lt;br /&gt;
          ap1.reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.reviews_by_reviewer(ap2).get_total_score&lt;br /&gt;
          ap2.reviews_by_reviewer(self).nil? ? next : s20 = ap2.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
          cycles.push([[self, s01], [ap1, s12], [ap2, s20]])&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def four_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
  def four_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap1|&lt;br /&gt;
      ap1.reviewers.each do |ap2|&lt;br /&gt;
        ap2.reviewers.each do |ap3|&lt;br /&gt;
          if ap3.reviewers.include?(self)&lt;br /&gt;
            self.reviews_by_reviewer(ap1).nil? ? next : s01 = self.reviews_by_reviewer(ap1).get_total_score&lt;br /&gt;
            ap1.reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.reviews_by_reviewer(ap2).get_total_score&lt;br /&gt;
            ap2.reviews_by_reviewer(ap3).nil? ? next : s23 = ap2.reviews_by_reviewer(ap3).get_total_score&lt;br /&gt;
            ap3.reviews_by_reviewer(self).nil? ? next : s30 = ap3.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
            cycles.push([[self, s01], [ap1, s12], [ap2, s23], [ap3, s30]])&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def cycle_similarity_score(cycle)'''&lt;br /&gt;
&lt;br /&gt;
  def cycle_similarity_score(cycle)&lt;br /&gt;
    similarity_score = 0.0&lt;br /&gt;
    count = 0.0&lt;br /&gt;
&lt;br /&gt;
    0 ... cycle.size-1.each do |pivot|&lt;br /&gt;
      pivot_score = cycle[pivot][1]&lt;br /&gt;
      similarity_score = similarity_score + (pivot_score - cycle[other][1]).abs&lt;br /&gt;
      count = count + 1.0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    similarity_score = similarity_score / count unless count == 0.0&lt;br /&gt;
    similarity_score&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def cycle_deviation_score(cycle)'''&lt;br /&gt;
&lt;br /&gt;
  def cycle_deviation_score(cycle)&lt;br /&gt;
    deviation_score = 0.0&lt;br /&gt;
    count = 0.0&lt;br /&gt;
&lt;br /&gt;
    0 ... cycle.size.each do |member|&lt;br /&gt;
      participant = AssignmentParticipant.find(cycle[member][0].id)&lt;br /&gt;
      total_score = participant.get_review_score&lt;br /&gt;
      deviation_score = deviation_score + (total_score - cycle[member][1]).abs&lt;br /&gt;
      count = count + 1.0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    deviation_score = deviation_score / count unless count == 0.0&lt;br /&gt;
    deviation_score&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def compute_quiz_scores(scores)'''&lt;br /&gt;
&lt;br /&gt;
  def compute_quiz_scores(scores)&lt;br /&gt;
    total = 0&lt;br /&gt;
    if scores[:quiz][:scores][:avg]&lt;br /&gt;
      return scores[:quiz][:scores][:avg] * 100  / 100.to_f&lt;br /&gt;
    else&lt;br /&gt;
      return 0&lt;br /&gt;
    end&lt;br /&gt;
    return total&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def review_response_maps'''&lt;br /&gt;
&lt;br /&gt;
  def review_response_maps&lt;br /&gt;
      participant = Participant.find(id)&lt;br /&gt;
      team_id = TeamsUser.team_id(participant.parent_id, participant.user_id)&lt;br /&gt;
      ReviewResponseMap.where(reviewee_id: team_id, reviewed_object_id: assignment.id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def members'''&lt;br /&gt;
&lt;br /&gt;
  def members&lt;br /&gt;
    team.try :participants&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def get_hash(time_stamp)'''&lt;br /&gt;
&lt;br /&gt;
  def get_hash(time_stamp)&lt;br /&gt;
    # first generate a hash from the assignment name itself&lt;br /&gt;
    hash_data = Digest::SHA1.digest(self.assignment.name.to_s)&lt;br /&gt;
&lt;br /&gt;
    # second generate a hash from the first hash plus the user name and time stamp&lt;br /&gt;
    sign = hash_data + self.user.name.to_s + time_stamp.strftime(&amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;)&lt;br /&gt;
    Digest::SHA1.digest(sign)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Review methods===&lt;br /&gt;
* The bookmark_reviews() method from AssignmentParticipant was being called once in '''get_assessments_for''' method of '''BookmarkRatingQuestionnaire''' class. It has been replaced by the method statement directly since it only had a single line of code.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def bookmark_reviews&lt;br /&gt;
    BookmarkRatingResponseMap.get_assessments_for(self)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
||&lt;br /&gt;
&lt;br /&gt;
  def get_assessments_for(participant)&lt;br /&gt;
    BookmarkRatingResponseMap.get_assessments_for(participant) # participant.bookmark_reviews()&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* The teammate_reviews() method from AssignmentParticipant was being called once in '''get_assessments_for''' method of '''TeammateReviewQuestionnaire''' class. It has been replaced by the method statement directly since it only had a single line of code.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def teammate_reviews&lt;br /&gt;
    TeammateReviewResponseMap.get_assessments_for(self)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
||&lt;br /&gt;
&lt;br /&gt;
  def get_assessments_for(participant)&lt;br /&gt;
    TeammateReviewResponseMap.get_assessments_for(participant)   #participant.teammate_reviews()&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
Please follow the below instruction to test UI:&lt;br /&gt;
* Login to Expertiza on http://152.46.20.199:3000/.&lt;br /&gt;
* Enter username as 'student13' and password as 'password'.&lt;br /&gt;
* You can select a previous assignment 'shivam test' or 'Pankti test'.&lt;br /&gt;
* You should be able to access the pages further&lt;br /&gt;
** Your team- The page content should be visible without any errors.&lt;br /&gt;
** Your work - The upload button for submission should be visible.&lt;br /&gt;
** Your scores- The page should give result 0 and not any error.&lt;br /&gt;
&lt;br /&gt;
When the user runs the application, the behavior of the application remains the same. &lt;br /&gt;
&lt;br /&gt;
The existing [https://en.wikipedia.org/wiki/RSpec RSpec] test cases remain successful. The same can be checked by running&lt;br /&gt;
Rspec spec&lt;br /&gt;
The participant is able to log in to the system, view the assignments, submit links and files in assignment submission, view the scores, review peers, etc. Below are some of the execution screenshots after the refactoring of the model.&lt;br /&gt;
&lt;br /&gt;
The Expertiza Login Screen&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaLoginScreen.jpg]]&lt;br /&gt;
&lt;br /&gt;
User can see all the assignments as below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS2.jpg]]&lt;br /&gt;
&lt;br /&gt;
View team members for the assignment selected. In this case, we have taken a dummy assignment we created.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS3.jpg]]&lt;br /&gt;
&lt;br /&gt;
View the submission page to upload the assignment.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS4.jpg]]&lt;br /&gt;
&lt;br /&gt;
View the scores of an assignment.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS5.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Resources==&lt;br /&gt;
* Expertiza Github repository&amp;lt;ref&amp;gt;Expertiza Github repository https://github.com/expertiza/expertiza&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Our Github repository&amp;lt;ref&amp;gt;Our Github Repository https://github.com/shivamgulati1991/expertiza]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/oss_E1562_APS&amp;diff=98332</id>
		<title>CSC/ECE 517 Fall 2015/oss E1562 APS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/oss_E1562_APS&amp;diff=98332"/>
		<updated>2015-11-06T15:38:18Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Formatted code snippet&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1562. Refactor AssignmentParticipant model'''&amp;lt;ref&amp;gt;Project Description document https://docs.google.com/document/d/1uWs3zyrupTmrOFuv5IbVWCF4NRvCXqJmg8dZ0wCqgus&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page provides a brief description of the '''Expertiza''' project. The project is aimed at refactoring the AssignmentParticipant model which is subclass of Participant model. This model is used to maintain the list of students/users participating in a given assignment. For any new or existing assignments, this model manages the entire list of users assigned to that particular assignment. It primarily includes method for scores calculations, assignment submission paths, reviews, etc. As part of this project, some of the methods have been removed which were not being used anywhere, some have been moved to their appropriate helper module and some have been refactored into smaller ones.&lt;br /&gt;
&lt;br /&gt;
==Introduction to Expertiza==&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system which provides incremental learning from the class. This project has been developed together by faculty and students using [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create, edit and delete assignments, create new assignment topics, assign them to a particular class or selected students, have students work on teams and then review each other's assignments at the end. For the students, they can signup for topics, form teams, and submit their projects and assignments. &lt;br /&gt;
Students then review the work done by other students and give suggestions to improve. Teams after reviews are allotted scores and they can refer to the peer comments to further improve their work. It also supports submission of different file types for assignments, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
==Why refactoring?==&lt;br /&gt;
'''Refactoring'''&amp;lt;ref&amp;gt;Refactoring https://en.wikipedia.org/wiki/Code_refactoring&amp;lt;/ref&amp;gt; is restructuring of code without the need of changing any external behavior. It reduces complexity and improves readability. It also becomes easy to extend the application with respect to different modules and their functionalities.&lt;br /&gt;
Some common techniques to refactor are:&lt;br /&gt;
&lt;br /&gt;
* Moving methods to appropriate modules&lt;br /&gt;
* Breaking methods into more meaningful functionality&lt;br /&gt;
* Creating more generalized code.&lt;br /&gt;
* Renaming methods and variable.&lt;br /&gt;
* Inheritance&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
Refactor '''AssignmentParticipant''' model which is a subclass of '''Participant''' model.&lt;br /&gt;
The following tasks have been performed as per the requirements.&lt;br /&gt;
&lt;br /&gt;
* Refactor scores method to smaller methods.&lt;br /&gt;
* In set_handle method, there is no need for a separate ELSEIF statement. Club the ELSEIF statement into IF statement as an another OR condition.&lt;br /&gt;
* Remove methods like compute_quiz_scores(scores) , average_score_per_assignment(assignment_id) which are not being used.&lt;br /&gt;
* Method cycle_deviation_score(cycle) is also present in CollusionCycle, remove it from this class.&lt;br /&gt;
* Methods related to reviews like teammate_reviews, bookmark_reviews do not belong to AssignmentParticipant model. Move them to the appropriate class.&lt;br /&gt;
* Methods related to files and directories like files(directory) should not be present in AssignmentParticipant model, move them to FileHelper module.&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
===Scores method===&lt;br /&gt;
The method '''scores''' has been converted to smaller methods '''scores''', '''assignment_questionnaires''',  '''merge_scores''', '''calculate_scores'''. It is a good practice to keep the methods not extremely long as they tend to complicate the functionality and the readability.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Before!!After&lt;br /&gt;
|-&lt;br /&gt;
|def scores(questions)&lt;br /&gt;
    scores = {}&lt;br /&gt;
    scores[:participant] = self&lt;br /&gt;
    self.assignment.questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.find_by_assignment_id_and_questionnaire_id(self.assignment.id, questionnaire.id).used_in_round&lt;br /&gt;
      #create symbol for &amp;quot;varying rubrics&amp;quot; feature -Yang&lt;br /&gt;
      if(round!=nil)&lt;br /&gt;
        questionnaire_symbol = (questionnaire.symbol.to_s+round.to_s).to_sym&lt;br /&gt;
      else&lt;br /&gt;
        questionnaire_symbol = questionnaire.symbol&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[questionnaire_symbol] = {}&lt;br /&gt;
&lt;br /&gt;
      if round==nil&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_for(self)&lt;br /&gt;
      else&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_round_for(self,round)&lt;br /&gt;
      end&lt;br /&gt;
      scores[questionnaire_symbol][:scores] = Answer.compute_scores(scores[questionnaire_symbol][:assessments], questions[questionnaire_symbol])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = self.assignment.compute_total_score(scores)&lt;br /&gt;
&lt;br /&gt;
    #merge scores[review#] (for each round) to score[review]  -Yang&lt;br /&gt;
    if self.assignment.varying_rubrics_by_round?&lt;br /&gt;
      review_sym = &amp;quot;review&amp;quot;.to_sym&lt;br /&gt;
      scores[review_sym] = Hash.new&lt;br /&gt;
      scores[review_sym][:assessments] = Array.new&lt;br /&gt;
      scores[review_sym][:scores] = Hash.new&lt;br /&gt;
      scores[review_sym][:scores][:max] = -999999999&lt;br /&gt;
      scores[review_sym][:scores][:min] = 999999999&lt;br /&gt;
      scores[review_sym][:scores][:avg] = 0&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      for i in 1..self.assignment.get_review_rounds&lt;br /&gt;
        round_sym = (&amp;quot;review&amp;quot;+i.to_s).to_sym&lt;br /&gt;
        if scores[round_sym][:assessments].nil? || scores[round_sym][:assessments].length==0&lt;br /&gt;
          next&lt;br /&gt;
        end&lt;br /&gt;
        length_of_assessments=scores[round_sym][:assessments].length.to_f&lt;br /&gt;
&lt;br /&gt;
        scores[review_sym][:assessments]+=scores[round_sym][:assessments]&lt;br /&gt;
&lt;br /&gt;
        if(scores[round_sym][:scores][:max]!=nil &amp;amp;&amp;amp; scores[review_sym][:scores][:max]&amp;lt;scores[round_sym][:scores][:max])&lt;br /&gt;
          scores[review_sym][:scores][:max]= scores[round_sym][:scores][:max]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:min]!= nil &amp;amp;&amp;amp; scores[review_sym][:scores][:min]&amp;gt;scores[round_sym][:scores][:min])&lt;br /&gt;
          scores[review_sym][:scores][:min]= scores[round_sym][:scores][:min]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:avg]!=nil)&lt;br /&gt;
          total_score += scores[round_sym][:scores][:avg]*length_of_assessments&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      if scores[review_sym][:scores][:max] == -999999999 &amp;amp;&amp;amp; scores[review_sym][:scores][:min] == 999999999&lt;br /&gt;
               scores[review_sym][:scores][:max] = 0&lt;br /&gt;
               scores[review_sym][:scores][:min] = 0&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[review_sym][:scores][:avg] = total_score/scores[review_sym][:assessments].length.to_f&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # In the event that this is a microtask, we need to scale the score accordingly and record the total possible points&lt;br /&gt;
    # PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else&lt;br /&gt;
    if assignment.is_microtask?&lt;br /&gt;
      topic = SignUpTopic.find_by_assignment_id(assignment.id)&lt;br /&gt;
      if !topic.nil?&lt;br /&gt;
        scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)&lt;br /&gt;
        scores[:max_pts_available] = topic.micropayment&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # for all quiz questionnaires (quizzes) taken by the participant&lt;br /&gt;
    quiz_responses = Array.new&lt;br /&gt;
    quiz_response_mappings = QuizResponseMap.where(reviewer_id: self.id)&lt;br /&gt;
    quiz_response_mappings.each do |qmapping|&lt;br /&gt;
      if (qmapping.response)&lt;br /&gt;
        quiz_responses &amp;lt;&amp;lt; qmapping.response&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #scores[:quiz] = Hash.new&lt;br /&gt;
    #scores[:quiz][:assessments] = quiz_responses&lt;br /&gt;
    #scores[:quiz][:scores] = Answer.compute_quiz_scores(scores[:quiz][:assessments])&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = assignment.compute_total_score(scores)&lt;br /&gt;
    #scores[:total_score] += compute_quiz_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    # move lots of calculation from view(_participant.html.erb) to model&lt;br /&gt;
    if self.grade&lt;br /&gt;
      scores[:total_score] = self.grade&lt;br /&gt;
    else&lt;br /&gt;
      total_score = scores[:total_score]&lt;br /&gt;
      if total_score &amp;gt; 100&lt;br /&gt;
        total_score = 100&lt;br /&gt;
      end&lt;br /&gt;
      scores[:total_score] = total_score&lt;br /&gt;
    scores&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
||&lt;br /&gt;
* scores(questions) method&lt;br /&gt;
&lt;br /&gt;
  def scores(questions)&lt;br /&gt;
    scores = {}&lt;br /&gt;
    scores[:participant] = self&lt;br /&gt;
&lt;br /&gt;
    assignment_questionnaires(questions, scores)&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = self.assignment.compute_total_score(scores)&lt;br /&gt;
&lt;br /&gt;
    merge_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    # In the event that this is a microtask, we need to scale the score accordingly and record the total possible points&lt;br /&gt;
    # PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else&lt;br /&gt;
    if assignment.is_microtask?&lt;br /&gt;
      topic = SignUpTopic.find_by_assignment_id(assignment.id)&lt;br /&gt;
      if !topic.nil?&lt;br /&gt;
        scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)&lt;br /&gt;
        scores[:max_pts_available] = topic.micropayment&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # for all quiz questionnaires (quizzes) taken by the participant&lt;br /&gt;
    quiz_responses = Array.new&lt;br /&gt;
    quiz_response_mappings = QuizResponseMap.where(reviewer_id: self.id)&lt;br /&gt;
    quiz_response_mappings.each do |qmapping|&lt;br /&gt;
      if (qmapping.response)&lt;br /&gt;
        quiz_responses &amp;lt;&amp;lt; qmapping.response&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #scores[:quiz] = Hash.new&lt;br /&gt;
    #scores[:quiz][:assessments] = quiz_responses&lt;br /&gt;
    #scores[:quiz][:scores] = Answer.compute_quiz_scores(scores[:quiz][:assessments])&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = assignment.compute_total_score(scores)&lt;br /&gt;
    #scores[:total_score] += compute_quiz_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    calculate_scores(scores)&lt;br /&gt;
  end&lt;br /&gt;
* assignment_questionnaires(questions, scores) method&lt;br /&gt;
&lt;br /&gt;
  def assignment_questionnaires(questions, scores)&lt;br /&gt;
    self.assignment.questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.find_by_assignment_id_and_questionnaire_id(self.assignment.id, questionnaire.id).used_in_round&lt;br /&gt;
      #create symbol for &amp;quot;varying rubrics&amp;quot; feature -Yang&lt;br /&gt;
      if(round!=nil)&lt;br /&gt;
        questionnaire_symbol = (questionnaire.symbol.to_s+round.to_s).to_sym&lt;br /&gt;
      else&lt;br /&gt;
        questionnaire_symbol = questionnaire.symbol&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[questionnaire_symbol] = {}&lt;br /&gt;
&lt;br /&gt;
      if round==nil&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_for(self)&lt;br /&gt;
      else&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_round_for(self,round)&lt;br /&gt;
      end&lt;br /&gt;
      scores[questionnaire_symbol][:scores] = Answer.compute_scores(scores[questionnaire_symbol][:assessments], questions[questionnaire_symbol])&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* merge_scores(scores) method&lt;br /&gt;
&lt;br /&gt;
  def merge_scores(scores)&lt;br /&gt;
    #merge scores[review#] (for each round) to score[review]  -Yang&lt;br /&gt;
    if self.assignment.varying_rubrics_by_round?&lt;br /&gt;
      review_sym = &amp;quot;review&amp;quot;.to_sym&lt;br /&gt;
      scores[review_sym] = Hash.new&lt;br /&gt;
      scores[review_sym][:assessments] = Array.new&lt;br /&gt;
      scores[review_sym][:scores] = Hash.new&lt;br /&gt;
      scores[review_sym][:scores][:max] = -999999999&lt;br /&gt;
      scores[review_sym][:scores][:min] = 999999999&lt;br /&gt;
      scores[review_sym][:scores][:avg] = 0&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      for i in 1..self.assignment.get_review_rounds&lt;br /&gt;
        round_sym = (&amp;quot;review&amp;quot;+i.to_s).to_sym&lt;br /&gt;
        if scores[round_sym][:assessments].nil? || scores[round_sym][:assessments].length==0&lt;br /&gt;
          next&lt;br /&gt;
        end&lt;br /&gt;
        length_of_assessments=scores[round_sym][:assessments].length.to_f&lt;br /&gt;
&lt;br /&gt;
        scores[review_sym][:assessments]+=scores[round_sym][:assessments]&lt;br /&gt;
&lt;br /&gt;
        if(scores[round_sym][:scores][:max]!=nil &amp;amp;&amp;amp; scores[review_sym][:scores][:max]&amp;lt;scores[round_sym][:scores][:max])&lt;br /&gt;
          scores[review_sym][:scores][:max]= scores[round_sym][:scores][:max]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:min]!= nil &amp;amp;&amp;amp; scores[review_sym][:scores][:min]&amp;gt;scores[round_sym][:scores][:min])&lt;br /&gt;
          scores[review_sym][:scores][:min]= scores[round_sym][:scores][:min]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:avg]!=nil)&lt;br /&gt;
          total_score += scores[round_sym][:scores][:avg]*length_of_assessments&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      if scores[review_sym][:scores][:max] == -999999999 &amp;amp;&amp;amp; scores[review_sym][:scores][:min] == 999999999&lt;br /&gt;
        scores[review_sym][:scores][:max] = 0&lt;br /&gt;
        scores[review_sym][:scores][:min] = 0&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[review_sym][:scores][:avg] = total_score/scores[review_sym][:assessments].length.to_f&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* calculate_scores(scores) method&lt;br /&gt;
&lt;br /&gt;
  def calculate_scores(scores)&lt;br /&gt;
    # move lots of calculation from view(_participant.html.erb) to model&lt;br /&gt;
    if self.grade&lt;br /&gt;
      scores[:total_score] = self.grade&lt;br /&gt;
    else&lt;br /&gt;
      total_score = scores[:total_score]&lt;br /&gt;
      if total_score &amp;gt; 100&lt;br /&gt;
        total_score = 100&lt;br /&gt;
      end&lt;br /&gt;
      scores[:total_score] = total_score&lt;br /&gt;
      scores&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===set_handle method===&lt;br /&gt;
The set_handle method had an unncessary ELSIF statement which was performing the same action '''self.handle = self.user.name'''. This has been clubbed as an OR condition to the IF statement and the first ELSIF statement has been removed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Old code'''&lt;br /&gt;
&lt;br /&gt;
  def set_handle&lt;br /&gt;
      if self.user.handle == nil or self.user.handle == &amp;quot;&amp;quot;&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      elsif AssignmentParticipant.where(parent_id: self.assignment.id, handle: self.user.handle).length &amp;gt; 0&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      else&lt;br /&gt;
        self.handle = self.user.handle&lt;br /&gt;
      end&lt;br /&gt;
      self.save!&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
'''New code'''&lt;br /&gt;
&lt;br /&gt;
  def set_handle&lt;br /&gt;
      if self.user.handle == nil or self.user.handle == &amp;quot;&amp;quot; or AssignmentParticipant.where(parent_id: self.assignment.id, handle: self.user.handle).length &amp;gt; 0&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      else&lt;br /&gt;
        self.handle = self.user.handle&lt;br /&gt;
      end&lt;br /&gt;
      self.save!&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===File and directory methods===&lt;br /&gt;
The files and directory methods from AssignmentParticipant model have been moved to the '''FileHelper''' module.&lt;br /&gt;
The methods '''files''', '''submitted_files''' and '''dir_path''' are appropriate for the '''FileHelper' module and hence been moved there.&lt;br /&gt;
The below line was added to the AssignmentParticipant model.&lt;br /&gt;
include FileHelper&lt;br /&gt;
&lt;br /&gt;
The AssignmentParticipant class would look like&lt;br /&gt;
  class AssignmentParticipant &amp;lt; Participant&lt;br /&gt;
    require 'wiki_helper'&lt;br /&gt;
    '''include FileHelper'''&lt;br /&gt;
Methods moved to FileHelper:&lt;br /&gt;
&lt;br /&gt;
* submitted_files&lt;br /&gt;
&lt;br /&gt;
  def submitted_files&lt;br /&gt;
    files(self.path) if self.directory_num&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* files(directory)&lt;br /&gt;
&lt;br /&gt;
  def files(directory)&lt;br /&gt;
    files_list = Dir[directory + &amp;quot;/*&amp;quot;]&lt;br /&gt;
    files = Array.new&lt;br /&gt;
&lt;br /&gt;
    files_list.each do |file|&lt;br /&gt;
      if File.directory?(file)&lt;br /&gt;
        dir_files = files(file)&lt;br /&gt;
        dir_files.each{|f| files &amp;lt;&amp;lt; f}&lt;br /&gt;
      end&lt;br /&gt;
      files &amp;lt;&amp;lt; file&lt;br /&gt;
    end&lt;br /&gt;
    files&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* submitted_files()&lt;br /&gt;
&lt;br /&gt;
  def submitted_files()&lt;br /&gt;
    files = Array.new&lt;br /&gt;
    if(self.directory_num)&lt;br /&gt;
      files = files(self.path)&lt;br /&gt;
    end&lt;br /&gt;
    return files&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* dir_path&lt;br /&gt;
&lt;br /&gt;
  def dir_path&lt;br /&gt;
    assignment.try :directory_path&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Remove unused methods===&lt;br /&gt;
The following methods have been removed as they were not being used by the application.&lt;br /&gt;
&lt;br /&gt;
'''def average_score_per_assignment(assignment_id)'''&lt;br /&gt;
&lt;br /&gt;
 def average_score_per_assignment(assignment_id)&lt;br /&gt;
    return 0 if self.response_maps.size == 0&lt;br /&gt;
&lt;br /&gt;
    sum_of_scores = 0&lt;br /&gt;
&lt;br /&gt;
    self.response_maps.metareview_response_maps.each do |metaresponse_map|&lt;br /&gt;
      if !metaresponse_map.response.empty? &amp;amp;&amp;amp; response_map == assignment_id then&lt;br /&gt;
        sum_of_scores = sum_of_scores + response_map.response.last.average_score&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    (sum_of_scores / self.response_maps.size).to_i&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def quiz_taken_by?(contributor, reviewer)'''&lt;br /&gt;
&lt;br /&gt;
  def quiz_taken_by?(contributor, reviewer)&lt;br /&gt;
    quiz_id = QuizQuestionnaire.find_by_instructor_id(contributor.id)&lt;br /&gt;
    return QuizResponseMap.where(['reviewee_id = ? AND reviewer_id = ? AND reviewed_object_id = ?',&lt;br /&gt;
                                  self.id, reviewer.id, quiz_id]).count &amp;gt; 0&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def has_quiz?'''&lt;br /&gt;
&lt;br /&gt;
  def has_quiz?&lt;br /&gt;
    return !QuizQuestionnaire.find_by_instructor_id(self.id).nil?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def reviewees'''&lt;br /&gt;
&lt;br /&gt;
  def reviewees&lt;br /&gt;
    reviewees = []&lt;br /&gt;
    rmaps = ResponseMap.all(conditions: [&amp;quot;reviewer_id = #{self.id} &amp;amp;&amp;amp; type = 'ReviewResponseMap'&amp;quot;])&lt;br /&gt;
        rmaps.each { |rm| reviewees.concat(AssignmentTeam.find(rm.reviewee_id).participants) }&lt;br /&gt;
&lt;br /&gt;
    reviewees&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def two_node_cycles'''&lt;br /&gt;
 &lt;br /&gt;
  def two_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap|&lt;br /&gt;
      if ap.reviewers.include?(self)&lt;br /&gt;
        self.reviews_by_reviewer(ap).nil? ? next : s01 = self.reviews_by_reviewer(ap).get_total_score&lt;br /&gt;
        ap.reviews_by_reviewer(self).nil? ? next : s10 = ap.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
        cycles.push([[self, s01], [ap, s10]])&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def three_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
  def three_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap1|&lt;br /&gt;
      ap1.reviewers.each do |ap2|&lt;br /&gt;
        if ap2.reviewers.include?(self)&lt;br /&gt;
          self.reviews_by_reviewer(ap1).nil? ? next : s01 = self.reviews_by_reviewer(ap1).get_total_score&lt;br /&gt;
          ap1.reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.reviews_by_reviewer(ap2).get_total_score&lt;br /&gt;
          ap2.reviews_by_reviewer(self).nil? ? next : s20 = ap2.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
          cycles.push([[self, s01], [ap1, s12], [ap2, s20]])&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def four_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
  def four_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap1|&lt;br /&gt;
      ap1.reviewers.each do |ap2|&lt;br /&gt;
        ap2.reviewers.each do |ap3|&lt;br /&gt;
          if ap3.reviewers.include?(self)&lt;br /&gt;
            self.reviews_by_reviewer(ap1).nil? ? next : s01 = self.reviews_by_reviewer(ap1).get_total_score&lt;br /&gt;
            ap1.reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.reviews_by_reviewer(ap2).get_total_score&lt;br /&gt;
            ap2.reviews_by_reviewer(ap3).nil? ? next : s23 = ap2.reviews_by_reviewer(ap3).get_total_score&lt;br /&gt;
            ap3.reviews_by_reviewer(self).nil? ? next : s30 = ap3.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
            cycles.push([[self, s01], [ap1, s12], [ap2, s23], [ap3, s30]])&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def cycle_similarity_score(cycle)'''&lt;br /&gt;
&lt;br /&gt;
  def cycle_similarity_score(cycle)&lt;br /&gt;
    similarity_score = 0.0&lt;br /&gt;
    count = 0.0&lt;br /&gt;
&lt;br /&gt;
    0 ... cycle.size-1.each do |pivot|&lt;br /&gt;
      pivot_score = cycle[pivot][1]&lt;br /&gt;
      similarity_score = similarity_score + (pivot_score - cycle[other][1]).abs&lt;br /&gt;
      count = count + 1.0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    similarity_score = similarity_score / count unless count == 0.0&lt;br /&gt;
    similarity_score&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def cycle_deviation_score(cycle)'''&lt;br /&gt;
&lt;br /&gt;
  def cycle_deviation_score(cycle)&lt;br /&gt;
    deviation_score = 0.0&lt;br /&gt;
    count = 0.0&lt;br /&gt;
&lt;br /&gt;
    0 ... cycle.size.each do |member|&lt;br /&gt;
      participant = AssignmentParticipant.find(cycle[member][0].id)&lt;br /&gt;
      total_score = participant.get_review_score&lt;br /&gt;
      deviation_score = deviation_score + (total_score - cycle[member][1]).abs&lt;br /&gt;
      count = count + 1.0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    deviation_score = deviation_score / count unless count == 0.0&lt;br /&gt;
    deviation_score&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def compute_quiz_scores(scores)'''&lt;br /&gt;
&lt;br /&gt;
  def compute_quiz_scores(scores)&lt;br /&gt;
    total = 0&lt;br /&gt;
    if scores[:quiz][:scores][:avg]&lt;br /&gt;
      return scores[:quiz][:scores][:avg] * 100  / 100.to_f&lt;br /&gt;
    else&lt;br /&gt;
      return 0&lt;br /&gt;
    end&lt;br /&gt;
    return total&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def review_response_maps'''&lt;br /&gt;
&lt;br /&gt;
  def review_response_maps&lt;br /&gt;
      participant = Participant.find(id)&lt;br /&gt;
      team_id = TeamsUser.team_id(participant.parent_id, participant.user_id)&lt;br /&gt;
      ReviewResponseMap.where(reviewee_id: team_id, reviewed_object_id: assignment.id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def members'''&lt;br /&gt;
&lt;br /&gt;
  def members&lt;br /&gt;
    team.try :participants&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def get_hash(time_stamp)'''&lt;br /&gt;
&lt;br /&gt;
  def get_hash(time_stamp)&lt;br /&gt;
    # first generate a hash from the assignment name itself&lt;br /&gt;
    hash_data = Digest::SHA1.digest(self.assignment.name.to_s)&lt;br /&gt;
&lt;br /&gt;
    # second generate a hash from the first hash plus the user name and time stamp&lt;br /&gt;
    sign = hash_data + self.user.name.to_s + time_stamp.strftime(&amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;)&lt;br /&gt;
    Digest::SHA1.digest(sign)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Review methods===&lt;br /&gt;
* The bookmark_reviews() method from AssignmentParticipant was being called once in '''get_assessments_for''' method of '''BookmarkRatingQuestionnaire''' class. It has been replaced by the method statement directly since it only had a single line of code.&lt;br /&gt;
&lt;br /&gt;
'''Old Code'''&lt;br /&gt;
&lt;br /&gt;
  def bookmark_reviews&lt;br /&gt;
    BookmarkRatingResponseMap.get_assessments_for(self)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
'''New Code'''&lt;br /&gt;
&lt;br /&gt;
  def get_assessments_for(participant)&lt;br /&gt;
    BookmarkRatingResponseMap.get_assessments_for(participant) # participant.bookmark_reviews()&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* The teammate_reviews() method from AssignmentParticipant was being called once in '''get_assessments_for''' method of '''TeammateReviewQuestionnaire''' class. It has been replaced by the method statement directly since it only had a single line of code.&lt;br /&gt;
&lt;br /&gt;
'''Old Code'''&lt;br /&gt;
&lt;br /&gt;
  def teammate_reviews&lt;br /&gt;
    TeammateReviewResponseMap.get_assessments_for(self)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
'''New Code'''&lt;br /&gt;
&lt;br /&gt;
  def get_assessments_for(participant)&lt;br /&gt;
    TeammateReviewResponseMap.get_assessments_for(participant)   #participant.teammate_reviews()&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
Please follow the below instruction to test UI:&lt;br /&gt;
* Login to Expertiza on http://152.46.20.199:3000/.&lt;br /&gt;
* Enter username as 'student13' and password as 'password'.&lt;br /&gt;
* You can select a previous assignment 'shivam test' or 'Pankti test'.&lt;br /&gt;
* You should be able to access the pages further&lt;br /&gt;
** Your team- The page content should be visible without any errors.&lt;br /&gt;
** Your work - The upload button for submission should be visible.&lt;br /&gt;
** Your scores- The page should give result 0 and not any error.&lt;br /&gt;
&lt;br /&gt;
When the user runs the application, the behavior of the application remains the same. &lt;br /&gt;
&lt;br /&gt;
The existing [https://en.wikipedia.org/wiki/RSpec RSpec] test cases remain successful. The same can be checked by running&lt;br /&gt;
Rspec spec&lt;br /&gt;
The participant is able to log in to the system, view the assignments, submit links and files in assignment submission, view the scores, review peers, etc. Below are some of the execution screenshots after the refactoring of the model.&lt;br /&gt;
&lt;br /&gt;
The Expertiza Login Screen&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaLoginScreen.jpg]]&lt;br /&gt;
&lt;br /&gt;
User can see all the assignments as below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS2.jpg]]&lt;br /&gt;
&lt;br /&gt;
View team members for the assignment selected. In this case, we have taken a dummy assignment we created.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS3.jpg]]&lt;br /&gt;
&lt;br /&gt;
View the submission page to upload the assignment.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS4.jpg]]&lt;br /&gt;
&lt;br /&gt;
View the scores of an assignment.&lt;br /&gt;
&lt;br /&gt;
[[File:ExpertizaAPS5.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Resources==&lt;br /&gt;
* Expertiza Github repository&amp;lt;ref&amp;gt;Expertiza Github repository https://github.com/expertiza/expertiza&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Our Github repository&amp;lt;ref&amp;gt;Our Github Repository https://github.com/shivamgulati1991/expertiza]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/oss_E1562_APS&amp;diff=98009</id>
		<title>CSC/ECE 517 Fall 2015/oss E1562 APS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/oss_E1562_APS&amp;diff=98009"/>
		<updated>2015-11-01T02:29:09Z</updated>

		<summary type="html">&lt;p&gt;Prdesai2: Added refactoring points and code snippet.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1562. Refactor AssignmentParticipant model'''&amp;lt;ref&amp;gt;https://docs.google.com/document/d/1uWs3zyrupTmrOFuv5IbVWCF4NRvCXqJmg8dZ0wCqgus&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page provides a brief description of the Expertiza project. The project is aimed at refactoring the AssignmentParticipant model which is subclass of Participant model. This model is used to maintain the list of students/users participating in a given assignment.&lt;br /&gt;
&lt;br /&gt;
==Introduction to Expertiza==&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system which provides incremental learning from the class. This project has been developed together by faculty and students using [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create, edit and delete assignments, create new assignment topics, assign them to a particular class or selected students, have students work on teams and then review each other's assignments at the end. For the students, they can signup for topics, form teams, and submit their projects and assignments. &lt;br /&gt;
Students then review the work done by other students and give suggestions to improve. Teams after reviews are allotted scores and they can refer to the peer comments to further improve their work. It also supports submission of different file types for assignments, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
Refactor '''AssignmentParticipant''' model which is a subclass of '''Participant''' model.&lt;br /&gt;
&lt;br /&gt;
===Tasks to be performed===&lt;br /&gt;
* Refactor scores method to smaller methods.&lt;br /&gt;
* In set_handle method, there is no need for a separate ELSEIF statement. Club the ELSEIF statement into IF statement as an another OR condition.&lt;br /&gt;
* Remove methods like compute_quiz_scores(scores) , average_score_per_assignment(assignment_id) which are not being used.&lt;br /&gt;
* Method cycle_deviation_score(cycle) is also present in CollusionCycle, remove it from this class.&lt;br /&gt;
* Methods related to reviews like teammate_reviews, bookmark_reviews do not belong to AssignmentParticipant model. Move them to the appropriate class.&lt;br /&gt;
* Methods related to files and directories like files(directory) should not be present in AssignmentParticipant model, move them to FileHelper module.&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
===Scores method===&lt;br /&gt;
The method '''scores''' has been converted to smaller methods '''scores''', '''assignment_questionnaires''',  '''merge_scores''', '''calculate_scores'''.&lt;br /&gt;
&lt;br /&gt;
'''Old code'''&lt;br /&gt;
def scores(questions)&lt;br /&gt;
    scores = {}&lt;br /&gt;
    scores[:participant] = self&lt;br /&gt;
    self.assignment.questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.find_by_assignment_id_and_questionnaire_id(self.assignment.id, questionnaire.id).used_in_round&lt;br /&gt;
      #create symbol for &amp;quot;varying rubrics&amp;quot; feature -Yang&lt;br /&gt;
      if(round!=nil)&lt;br /&gt;
        questionnaire_symbol = (questionnaire.symbol.to_s+round.to_s).to_sym&lt;br /&gt;
      else&lt;br /&gt;
        questionnaire_symbol = questionnaire.symbol&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[questionnaire_symbol] = {}&lt;br /&gt;
&lt;br /&gt;
      if round==nil&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_for(self)&lt;br /&gt;
      else&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_round_for(self,round)&lt;br /&gt;
      end&lt;br /&gt;
      scores[questionnaire_symbol][:scores] = Answer.compute_scores(scores[questionnaire_symbol][:assessments], questions[questionnaire_symbol])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = self.assignment.compute_total_score(scores)&lt;br /&gt;
&lt;br /&gt;
    #merge scores[review#] (for each round) to score[review]  -Yang&lt;br /&gt;
    if self.assignment.varying_rubrics_by_round?&lt;br /&gt;
      review_sym = &amp;quot;review&amp;quot;.to_sym&lt;br /&gt;
      scores[review_sym] = Hash.new&lt;br /&gt;
      scores[review_sym][:assessments] = Array.new&lt;br /&gt;
      scores[review_sym][:scores] = Hash.new&lt;br /&gt;
      scores[review_sym][:scores][:max] = -999999999&lt;br /&gt;
      scores[review_sym][:scores][:min] = 999999999&lt;br /&gt;
      scores[review_sym][:scores][:avg] = 0&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      for i in 1..self.assignment.get_review_rounds&lt;br /&gt;
        round_sym = (&amp;quot;review&amp;quot;+i.to_s).to_sym&lt;br /&gt;
        if scores[round_sym][:assessments].nil? || scores[round_sym][:assessments].length==0&lt;br /&gt;
          next&lt;br /&gt;
        end&lt;br /&gt;
        length_of_assessments=scores[round_sym][:assessments].length.to_f&lt;br /&gt;
&lt;br /&gt;
        scores[review_sym][:assessments]+=scores[round_sym][:assessments]&lt;br /&gt;
&lt;br /&gt;
        if(scores[round_sym][:scores][:max]!=nil &amp;amp;&amp;amp; scores[review_sym][:scores][:max]&amp;lt;scores[round_sym][:scores][:max])&lt;br /&gt;
          scores[review_sym][:scores][:max]= scores[round_sym][:scores][:max]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:min]!= nil &amp;amp;&amp;amp; scores[review_sym][:scores][:min]&amp;gt;scores[round_sym][:scores][:min])&lt;br /&gt;
          scores[review_sym][:scores][:min]= scores[round_sym][:scores][:min]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:avg]!=nil)&lt;br /&gt;
          total_score += scores[round_sym][:scores][:avg]*length_of_assessments&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      if scores[review_sym][:scores][:max] == -999999999 &amp;amp;&amp;amp; scores[review_sym][:scores][:min] == 999999999&lt;br /&gt;
               scores[review_sym][:scores][:max] = 0&lt;br /&gt;
               scores[review_sym][:scores][:min] = 0&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[review_sym][:scores][:avg] = total_score/scores[review_sym][:assessments].length.to_f&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # In the event that this is a microtask, we need to scale the score accordingly and record the total possible points&lt;br /&gt;
    # PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else&lt;br /&gt;
    if assignment.is_microtask?&lt;br /&gt;
      topic = SignUpTopic.find_by_assignment_id(assignment.id)&lt;br /&gt;
      if !topic.nil?&lt;br /&gt;
        scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)&lt;br /&gt;
        scores[:max_pts_available] = topic.micropayment&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # for all quiz questionnaires (quizzes) taken by the participant&lt;br /&gt;
    quiz_responses = Array.new&lt;br /&gt;
    quiz_response_mappings = QuizResponseMap.where(reviewer_id: self.id)&lt;br /&gt;
    quiz_response_mappings.each do |qmapping|&lt;br /&gt;
      if (qmapping.response)&lt;br /&gt;
        quiz_responses &amp;lt;&amp;lt; qmapping.response&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #scores[:quiz] = Hash.new&lt;br /&gt;
    #scores[:quiz][:assessments] = quiz_responses&lt;br /&gt;
    #scores[:quiz][:scores] = Answer.compute_quiz_scores(scores[:quiz][:assessments])&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = assignment.compute_total_score(scores)&lt;br /&gt;
    #scores[:total_score] += compute_quiz_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    # move lots of calculation from view(_participant.html.erb) to model&lt;br /&gt;
    if self.grade&lt;br /&gt;
      scores[:total_score] = self.grade&lt;br /&gt;
    else&lt;br /&gt;
      total_score = scores[:total_score]&lt;br /&gt;
      if total_score &amp;gt; 100&lt;br /&gt;
        total_score = 100&lt;br /&gt;
      end&lt;br /&gt;
      scores[:total_score] = total_score&lt;br /&gt;
    scores&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
'''New code'''&lt;br /&gt;
* scores(questions) method&lt;br /&gt;
&lt;br /&gt;
def scores(questions)&lt;br /&gt;
    scores = {}&lt;br /&gt;
    scores[:participant] = self&lt;br /&gt;
&lt;br /&gt;
    assignment_questionnaires(questions, scores)&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = self.assignment.compute_total_score(scores)&lt;br /&gt;
&lt;br /&gt;
    merge_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    # In the event that this is a microtask, we need to scale the score accordingly and record the total possible points&lt;br /&gt;
    # PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else&lt;br /&gt;
    if assignment.is_microtask?&lt;br /&gt;
      topic = SignUpTopic.find_by_assignment_id(assignment.id)&lt;br /&gt;
      if !topic.nil?&lt;br /&gt;
        scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)&lt;br /&gt;
        scores[:max_pts_available] = topic.micropayment&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # for all quiz questionnaires (quizzes) taken by the participant&lt;br /&gt;
    quiz_responses = Array.new&lt;br /&gt;
    quiz_response_mappings = QuizResponseMap.where(reviewer_id: self.id)&lt;br /&gt;
    quiz_response_mappings.each do |qmapping|&lt;br /&gt;
      if (qmapping.response)&lt;br /&gt;
        quiz_responses &amp;lt;&amp;lt; qmapping.response&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #scores[:quiz] = Hash.new&lt;br /&gt;
    #scores[:quiz][:assessments] = quiz_responses&lt;br /&gt;
    #scores[:quiz][:scores] = Answer.compute_quiz_scores(scores[:quiz][:assessments])&lt;br /&gt;
&lt;br /&gt;
    scores[:total_score] = assignment.compute_total_score(scores)&lt;br /&gt;
    #scores[:total_score] += compute_quiz_scores(scores)&lt;br /&gt;
&lt;br /&gt;
    calculate_scores(scores)&lt;br /&gt;
  end&lt;br /&gt;
* assignment_questionnaires(questions, scores) method&lt;br /&gt;
def assignment_questionnaires(questions, scores)&lt;br /&gt;
    self.assignment.questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.find_by_assignment_id_and_questionnaire_id(self.assignment.id, questionnaire.id).used_in_round&lt;br /&gt;
      #create symbol for &amp;quot;varying rubrics&amp;quot; feature -Yang&lt;br /&gt;
      if(round!=nil)&lt;br /&gt;
        questionnaire_symbol = (questionnaire.symbol.to_s+round.to_s).to_sym&lt;br /&gt;
      else&lt;br /&gt;
        questionnaire_symbol = questionnaire.symbol&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[questionnaire_symbol] = {}&lt;br /&gt;
&lt;br /&gt;
      if round==nil&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_for(self)&lt;br /&gt;
      else&lt;br /&gt;
        scores[questionnaire_symbol][:assessments] = questionnaire.get_assessments_round_for(self,round)&lt;br /&gt;
      end&lt;br /&gt;
      scores[questionnaire_symbol][:scores] = Answer.compute_scores(scores[questionnaire_symbol][:assessments], questions[questionnaire_symbol])&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* merge_scores(scores) method&lt;br /&gt;
&lt;br /&gt;
def merge_scores(scores)&lt;br /&gt;
    #merge scores[review#] (for each round) to score[review]  -Yang&lt;br /&gt;
    if self.assignment.varying_rubrics_by_round?&lt;br /&gt;
      review_sym = &amp;quot;review&amp;quot;.to_sym&lt;br /&gt;
      scores[review_sym] = Hash.new&lt;br /&gt;
      scores[review_sym][:assessments] = Array.new&lt;br /&gt;
      scores[review_sym][:scores] = Hash.new&lt;br /&gt;
      scores[review_sym][:scores][:max] = -999999999&lt;br /&gt;
      scores[review_sym][:scores][:min] = 999999999&lt;br /&gt;
      scores[review_sym][:scores][:avg] = 0&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      for i in 1..self.assignment.get_review_rounds&lt;br /&gt;
        round_sym = (&amp;quot;review&amp;quot;+i.to_s).to_sym&lt;br /&gt;
        if scores[round_sym][:assessments].nil? || scores[round_sym][:assessments].length==0&lt;br /&gt;
          next&lt;br /&gt;
        end&lt;br /&gt;
        length_of_assessments=scores[round_sym][:assessments].length.to_f&lt;br /&gt;
&lt;br /&gt;
        scores[review_sym][:assessments]+=scores[round_sym][:assessments]&lt;br /&gt;
&lt;br /&gt;
        if(scores[round_sym][:scores][:max]!=nil &amp;amp;&amp;amp; scores[review_sym][:scores][:max]&amp;lt;scores[round_sym][:scores][:max])&lt;br /&gt;
          scores[review_sym][:scores][:max]= scores[round_sym][:scores][:max]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:min]!= nil &amp;amp;&amp;amp; scores[review_sym][:scores][:min]&amp;gt;scores[round_sym][:scores][:min])&lt;br /&gt;
          scores[review_sym][:scores][:min]= scores[round_sym][:scores][:min]&lt;br /&gt;
        end&lt;br /&gt;
        if(scores[round_sym][:scores][:avg]!=nil)&lt;br /&gt;
          total_score += scores[round_sym][:scores][:avg]*length_of_assessments&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      if scores[review_sym][:scores][:max] == -999999999 &amp;amp;&amp;amp; scores[review_sym][:scores][:min] == 999999999&lt;br /&gt;
        scores[review_sym][:scores][:max] = 0&lt;br /&gt;
        scores[review_sym][:scores][:min] = 0&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      scores[review_sym][:scores][:avg] = total_score/scores[review_sym][:assessments].length.to_f&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* calculate_scores(scores) method&lt;br /&gt;
&lt;br /&gt;
def calculate_scores(scores)&lt;br /&gt;
    # move lots of calculation from view(_participant.html.erb) to model&lt;br /&gt;
    if self.grade&lt;br /&gt;
      scores[:total_score] = self.grade&lt;br /&gt;
    else&lt;br /&gt;
      total_score = scores[:total_score]&lt;br /&gt;
      if total_score &amp;gt; 100&lt;br /&gt;
        total_score = 100&lt;br /&gt;
      end&lt;br /&gt;
      scores[:total_score] = total_score&lt;br /&gt;
      scores&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===set_handle method===&lt;br /&gt;
The 'elseif' statement has been removed from '''set_handle''' method and clubbed in the if statement using an '''or''' condition.&lt;br /&gt;
&lt;br /&gt;
'''Old code'''&lt;br /&gt;
&lt;br /&gt;
def set_handle&lt;br /&gt;
      if self.user.handle == nil or self.user.handle == &amp;quot;&amp;quot;&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      elsif AssignmentParticipant.where(parent_id: self.assignment.id, handle: self.user.handle).length &amp;gt; 0&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      else&lt;br /&gt;
        self.handle = self.user.handle&lt;br /&gt;
      end&lt;br /&gt;
      self.save!&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
'''New code'''&lt;br /&gt;
&lt;br /&gt;
def set_handle&lt;br /&gt;
      if self.user.handle == nil or self.user.handle == &amp;quot;&amp;quot; or AssignmentParticipant.where(parent_id: self.assignment.id, handle: self.user.handle).length &amp;gt; 0&lt;br /&gt;
        self.handle = self.user.name&lt;br /&gt;
      else&lt;br /&gt;
        self.handle = self.user.handle&lt;br /&gt;
      end&lt;br /&gt;
      self.save!&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
===File and directory methods===&lt;br /&gt;
The files and directory methods from AssignmentParticipant model have been moved to the '''FileHelper''' module.&lt;br /&gt;
&lt;br /&gt;
The below line was added to the AssignmentParticipant model.&lt;br /&gt;
include FileHelper&lt;br /&gt;
The AssignmentParticipant class would like&lt;br /&gt;
class AssignmentParticipant &amp;lt; Participant&lt;br /&gt;
  require 'wiki_helper'&lt;br /&gt;
  include FileHelper&lt;br /&gt;
Methods moved to FileHelper:&lt;br /&gt;
* submitted_files&lt;br /&gt;
&lt;br /&gt;
def submitted_files&lt;br /&gt;
    files(self.path) if self.directory_num&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* files(directory)&lt;br /&gt;
&lt;br /&gt;
def files(directory)&lt;br /&gt;
    files_list = Dir[directory + &amp;quot;/*&amp;quot;]&lt;br /&gt;
    files = Array.new&lt;br /&gt;
&lt;br /&gt;
    files_list.each do |file|&lt;br /&gt;
      if File.directory?(file)&lt;br /&gt;
        dir_files = files(file)&lt;br /&gt;
        dir_files.each{|f| files &amp;lt;&amp;lt; f}&lt;br /&gt;
      end&lt;br /&gt;
      files &amp;lt;&amp;lt; file&lt;br /&gt;
    end&lt;br /&gt;
    files&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* submitted_files()&lt;br /&gt;
&lt;br /&gt;
def submitted_files()&lt;br /&gt;
    files = Array.new&lt;br /&gt;
    if(self.directory_num)&lt;br /&gt;
      files = files(self.path)&lt;br /&gt;
    end&lt;br /&gt;
    return files&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* dir_path&lt;br /&gt;
&lt;br /&gt;
def dir_path&lt;br /&gt;
    assignment.try :directory_path&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Remove unused methods===&lt;br /&gt;
The following methods have been removed as they were not being used by the class:&lt;br /&gt;
&lt;br /&gt;
'''def average_score_per_assignment(assignment_id)'''&lt;br /&gt;
&lt;br /&gt;
 def average_score_per_assignment(assignment_id)&lt;br /&gt;
    return 0 if self.response_maps.size == 0&lt;br /&gt;
&lt;br /&gt;
    sum_of_scores = 0&lt;br /&gt;
&lt;br /&gt;
    self.response_maps.metareview_response_maps.each do |metaresponse_map|&lt;br /&gt;
      if !metaresponse_map.response.empty? &amp;amp;&amp;amp; response_map == assignment_id then&lt;br /&gt;
        sum_of_scores = sum_of_scores + response_map.response.last.average_score&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    (sum_of_scores / self.response_maps.size).to_i&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def quiz_taken_by?(contributor, reviewer)'''&lt;br /&gt;
&lt;br /&gt;
def quiz_taken_by?(contributor, reviewer)&lt;br /&gt;
    quiz_id = QuizQuestionnaire.find_by_instructor_id(contributor.id)&lt;br /&gt;
    return QuizResponseMap.where(['reviewee_id = ? AND reviewer_id = ? AND reviewed_object_id = ?',&lt;br /&gt;
                                  self.id, reviewer.id, quiz_id]).count &amp;gt; 0&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def has_quiz?'''&lt;br /&gt;
&lt;br /&gt;
def has_quiz?&lt;br /&gt;
    return !QuizQuestionnaire.find_by_instructor_id(self.id).nil?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def reviewees'''&lt;br /&gt;
&lt;br /&gt;
def reviewees&lt;br /&gt;
    reviewees = []&lt;br /&gt;
    rmaps = ResponseMap.all(conditions: [&amp;quot;reviewer_id = #{self.id} &amp;amp;&amp;amp; type = 'ReviewResponseMap'&amp;quot;])&lt;br /&gt;
        rmaps.each { |rm| reviewees.concat(AssignmentTeam.find(rm.reviewee_id).participants) }&lt;br /&gt;
&lt;br /&gt;
    reviewees&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def two_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
def two_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap|&lt;br /&gt;
      if ap.reviewers.include?(self)&lt;br /&gt;
        self.reviews_by_reviewer(ap).nil? ? next : s01 = self.reviews_by_reviewer(ap).get_total_score&lt;br /&gt;
        ap.reviews_by_reviewer(self).nil? ? next : s10 = ap.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
        cycles.push([[self, s01], [ap, s10]])&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def three_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
def three_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap1|&lt;br /&gt;
      ap1.reviewers.each do |ap2|&lt;br /&gt;
        if ap2.reviewers.include?(self)&lt;br /&gt;
          self.reviews_by_reviewer(ap1).nil? ? next : s01 = self.reviews_by_reviewer(ap1).get_total_score&lt;br /&gt;
          ap1.reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.reviews_by_reviewer(ap2).get_total_score&lt;br /&gt;
          ap2.reviews_by_reviewer(self).nil? ? next : s20 = ap2.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
          cycles.push([[self, s01], [ap1, s12], [ap2, s20]])&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def four_node_cycles'''&lt;br /&gt;
&lt;br /&gt;
def four_node_cycles&lt;br /&gt;
    cycles = []&lt;br /&gt;
    self.reviewers.each do |ap1|&lt;br /&gt;
      ap1.reviewers.each do |ap2|&lt;br /&gt;
        ap2.reviewers.each do |ap3|&lt;br /&gt;
          if ap3.reviewers.include?(self)&lt;br /&gt;
            self.reviews_by_reviewer(ap1).nil? ? next : s01 = self.reviews_by_reviewer(ap1).get_total_score&lt;br /&gt;
            ap1.reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.reviews_by_reviewer(ap2).get_total_score&lt;br /&gt;
            ap2.reviews_by_reviewer(ap3).nil? ? next : s23 = ap2.reviews_by_reviewer(ap3).get_total_score&lt;br /&gt;
            ap3.reviews_by_reviewer(self).nil? ? next : s30 = ap3.reviews_by_reviewer(self).get_total_score&lt;br /&gt;
            cycles.push([[self, s01], [ap1, s12], [ap2, s23], [ap3, s30]])&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    cycles&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def cycle_similarity_score(cycle)'''&lt;br /&gt;
&lt;br /&gt;
def cycle_similarity_score(cycle)&lt;br /&gt;
    similarity_score = 0.0&lt;br /&gt;
    count = 0.0&lt;br /&gt;
&lt;br /&gt;
    0 ... cycle.size-1.each do |pivot|&lt;br /&gt;
      pivot_score = cycle[pivot][1]&lt;br /&gt;
      similarity_score = similarity_score + (pivot_score - cycle[other][1]).abs&lt;br /&gt;
      count = count + 1.0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    similarity_score = similarity_score / count unless count == 0.0&lt;br /&gt;
    similarity_score&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def cycle_deviation_score(cycle)'''&lt;br /&gt;
&lt;br /&gt;
def cycle_deviation_score(cycle)&lt;br /&gt;
    deviation_score = 0.0&lt;br /&gt;
    count = 0.0&lt;br /&gt;
&lt;br /&gt;
    0 ... cycle.size.each do |member|&lt;br /&gt;
      participant = AssignmentParticipant.find(cycle[member][0].id)&lt;br /&gt;
      total_score = participant.get_review_score&lt;br /&gt;
      deviation_score = deviation_score + (total_score - cycle[member][1]).abs&lt;br /&gt;
      count = count + 1.0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    deviation_score = deviation_score / count unless count == 0.0&lt;br /&gt;
    deviation_score&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def compute_quiz_scores(scores)'''&lt;br /&gt;
&lt;br /&gt;
def compute_quiz_scores(scores)&lt;br /&gt;
    total = 0&lt;br /&gt;
    if scores[:quiz][:scores][:avg]&lt;br /&gt;
      return scores[:quiz][:scores][:avg] * 100  / 100.to_f&lt;br /&gt;
    else&lt;br /&gt;
      return 0&lt;br /&gt;
    end&lt;br /&gt;
    return total&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def review_response_maps'''&lt;br /&gt;
&lt;br /&gt;
def review_response_maps&lt;br /&gt;
      participant = Participant.find(id)&lt;br /&gt;
      team_id = TeamsUser.team_id(participant.parent_id, participant.user_id)&lt;br /&gt;
      ReviewResponseMap.where(reviewee_id: team_id, reviewed_object_id: assignment.id)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def members'''&lt;br /&gt;
&lt;br /&gt;
def members&lt;br /&gt;
    team.try :participants&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''def get_hash(time_stamp)'''&lt;br /&gt;
&lt;br /&gt;
def get_hash(time_stamp)&lt;br /&gt;
    # first generate a hash from the assignment name itself&lt;br /&gt;
    hash_data = Digest::SHA1.digest(self.assignment.name.to_s)&lt;br /&gt;
&lt;br /&gt;
    # second generate a hash from the first hash plus the user name and time stamp&lt;br /&gt;
    sign = hash_data + self.user.name.to_s + time_stamp.strftime(&amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;)&lt;br /&gt;
    Digest::SHA1.digest(sign)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Review methods===&lt;br /&gt;
* The bookmark_reviews() method from AssignmentParticipant model have been moved to the '''BookmarkRatingQuestionnaire''' class.&lt;br /&gt;
&lt;br /&gt;
def get_assessments_for(participant)&lt;br /&gt;
    BookmarkRatingResponseMap.get_assessments_for(participant) # participant.bookmark_reviews()&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
* The teammmate_reviews() method from AssignmentParticipant model have been moved to the '''TeammateReviewQuestionnaire''' class.&lt;br /&gt;
&lt;br /&gt;
def get_assessments_for(participant)&lt;br /&gt;
    TeammateReviewResponseMap.get_assessments_for(participant)   #participant.teammate_reviews()&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
When the user runs the application, the behavior of the application remains the same. &lt;br /&gt;
&lt;br /&gt;
The existing [[RSpec]] test cases remain successful. The same can be checked by running&lt;br /&gt;
Rspec spec&lt;br /&gt;
The participant is able to log in to the system, view the assignments, submit links and files in assignment submission, view the scores, review peers, etc. Below are some of the execution screenshots after the refactoring of the model.&lt;br /&gt;
&lt;br /&gt;
[[File:Login to expertiza from here.png]]&lt;br /&gt;
[[File:Expertiza test1.png]]&lt;br /&gt;
[[File:Expertiza test2.png]]&lt;br /&gt;
[[File:Expertiza test3.png]]&lt;br /&gt;
[[File:Expertiza test4.png]]&lt;br /&gt;
==Resources==&lt;br /&gt;
# Github repository&amp;lt;ref&amp;gt;https://github.com/expertiza/expertiza&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prdesai2</name></author>
	</entry>
</feed>