Applying Observer-Observable pattern to a code and multithreading
$begingroup$
I have to:
1) Apply the Observer-Observable pattern to the original code.
2) starting from the original code, I have to suppose that the modification of the array fields (slot machine numbers) should be done in parallel by 3 NumberGenerator threads instead of just one.
My output seems to work fine but I'm wondering if my implemention is good enough or if am I doing something wrong. Could you tell me if my code is good or not?
ORIGINAL CODE:
import java.util.*;
public class SlotMachineApp {
private static final int N = 3;
public static void main(String args) {
Numbers numeri = new Numbers(N);
(new NumberGenerator(numeri)).start();
}
}
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numeri) {
nums = numeri;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
nums.print();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public int getNum() {
return items.length;
}
public void set(int index, int x) {
items[index] = x;
}
public void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
OBSERVER-OBSERVABLE IMPLEMENTATION:
Model:
package slot;
import static java.lang.Thread.sleep;
import java.util.Observable;
import java.util.Random;
public class Model extends Observable {
private static final int N = 3;
Numbers numbers = new Numbers(N);
NumberGenerator ng = new NumberGenerator(numbers);
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numbers) {
nums = numbers;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
setChanged();
notifyObservers();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public int getNum() {
return items.length;
}
public void set(int index, int x) {
items[index] = x;
}
public void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
}
View:
package slot;
import java.util.Observable;
import java.util.Observer;
public class View implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o != null && o instanceof Model) {
((Model) o).numbers.print();
}
}
}
Controller:
package slot;
public class Controller {
private Model model;
private View view;
public Controller(Model m, View v){
this.model = m;
this.view =v;
}
}
Main:
package slot;
public class Slot {
public static void main(String args) {
Model model = new Model();
View view = new View();
Controller controller = new Controller(model, view);
model.addObserver(view);
model.ng.start();
}
}
MVC is not required I just like to use it for practice! If I did something wrong even in the MVC I would like to know please! I know that my Controller is doing nothing but actually I don't know which method to put inside to let Model and View comunicate since Observer-Observable calls update() from model to view.
Thread - Implementation with 3 NumberGenerator:
import java.util.*;
public class SlotMachineApp {
private static final int N = 3;
public static void main(String args) {
Numbers numbers = new Numbers(N);
NumberGenerator ng1 = new NumberGenerator(numbers);
NumberGenerator ng2 = new NumberGenerator(numbers);
NumberGenerator ng3 = new NumberGenerator(numbers);
ng1.start();
ng2.start();
ng3.start();
}
}
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numbers) {
nums = numbers;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
nums.print();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public synchronized int getNum() {
return items.length;
}
public synchronized void set(int index, int x) {
items[index] = x;
}
public synchronized void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
I modified the getNum (), set(), and print() methods by adding the keyword synchronized because I think that in this way each thread can work on its own avoiding race condition.
java multithreading mvc observer-pattern
New contributor
$endgroup$
add a comment |
$begingroup$
I have to:
1) Apply the Observer-Observable pattern to the original code.
2) starting from the original code, I have to suppose that the modification of the array fields (slot machine numbers) should be done in parallel by 3 NumberGenerator threads instead of just one.
My output seems to work fine but I'm wondering if my implemention is good enough or if am I doing something wrong. Could you tell me if my code is good or not?
ORIGINAL CODE:
import java.util.*;
public class SlotMachineApp {
private static final int N = 3;
public static void main(String args) {
Numbers numeri = new Numbers(N);
(new NumberGenerator(numeri)).start();
}
}
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numeri) {
nums = numeri;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
nums.print();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public int getNum() {
return items.length;
}
public void set(int index, int x) {
items[index] = x;
}
public void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
OBSERVER-OBSERVABLE IMPLEMENTATION:
Model:
package slot;
import static java.lang.Thread.sleep;
import java.util.Observable;
import java.util.Random;
public class Model extends Observable {
private static final int N = 3;
Numbers numbers = new Numbers(N);
NumberGenerator ng = new NumberGenerator(numbers);
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numbers) {
nums = numbers;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
setChanged();
notifyObservers();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public int getNum() {
return items.length;
}
public void set(int index, int x) {
items[index] = x;
}
public void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
}
View:
package slot;
import java.util.Observable;
import java.util.Observer;
public class View implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o != null && o instanceof Model) {
((Model) o).numbers.print();
}
}
}
Controller:
package slot;
public class Controller {
private Model model;
private View view;
public Controller(Model m, View v){
this.model = m;
this.view =v;
}
}
Main:
package slot;
public class Slot {
public static void main(String args) {
Model model = new Model();
View view = new View();
Controller controller = new Controller(model, view);
model.addObserver(view);
model.ng.start();
}
}
MVC is not required I just like to use it for practice! If I did something wrong even in the MVC I would like to know please! I know that my Controller is doing nothing but actually I don't know which method to put inside to let Model and View comunicate since Observer-Observable calls update() from model to view.
Thread - Implementation with 3 NumberGenerator:
import java.util.*;
public class SlotMachineApp {
private static final int N = 3;
public static void main(String args) {
Numbers numbers = new Numbers(N);
NumberGenerator ng1 = new NumberGenerator(numbers);
NumberGenerator ng2 = new NumberGenerator(numbers);
NumberGenerator ng3 = new NumberGenerator(numbers);
ng1.start();
ng2.start();
ng3.start();
}
}
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numbers) {
nums = numbers;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
nums.print();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public synchronized int getNum() {
return items.length;
}
public synchronized void set(int index, int x) {
items[index] = x;
}
public synchronized void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
I modified the getNum (), set(), and print() methods by adding the keyword synchronized because I think that in this way each thread can work on its own avoiding race condition.
java multithreading mvc observer-pattern
New contributor
$endgroup$
add a comment |
$begingroup$
I have to:
1) Apply the Observer-Observable pattern to the original code.
2) starting from the original code, I have to suppose that the modification of the array fields (slot machine numbers) should be done in parallel by 3 NumberGenerator threads instead of just one.
My output seems to work fine but I'm wondering if my implemention is good enough or if am I doing something wrong. Could you tell me if my code is good or not?
ORIGINAL CODE:
import java.util.*;
public class SlotMachineApp {
private static final int N = 3;
public static void main(String args) {
Numbers numeri = new Numbers(N);
(new NumberGenerator(numeri)).start();
}
}
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numeri) {
nums = numeri;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
nums.print();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public int getNum() {
return items.length;
}
public void set(int index, int x) {
items[index] = x;
}
public void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
OBSERVER-OBSERVABLE IMPLEMENTATION:
Model:
package slot;
import static java.lang.Thread.sleep;
import java.util.Observable;
import java.util.Random;
public class Model extends Observable {
private static final int N = 3;
Numbers numbers = new Numbers(N);
NumberGenerator ng = new NumberGenerator(numbers);
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numbers) {
nums = numbers;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
setChanged();
notifyObservers();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public int getNum() {
return items.length;
}
public void set(int index, int x) {
items[index] = x;
}
public void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
}
View:
package slot;
import java.util.Observable;
import java.util.Observer;
public class View implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o != null && o instanceof Model) {
((Model) o).numbers.print();
}
}
}
Controller:
package slot;
public class Controller {
private Model model;
private View view;
public Controller(Model m, View v){
this.model = m;
this.view =v;
}
}
Main:
package slot;
public class Slot {
public static void main(String args) {
Model model = new Model();
View view = new View();
Controller controller = new Controller(model, view);
model.addObserver(view);
model.ng.start();
}
}
MVC is not required I just like to use it for practice! If I did something wrong even in the MVC I would like to know please! I know that my Controller is doing nothing but actually I don't know which method to put inside to let Model and View comunicate since Observer-Observable calls update() from model to view.
Thread - Implementation with 3 NumberGenerator:
import java.util.*;
public class SlotMachineApp {
private static final int N = 3;
public static void main(String args) {
Numbers numbers = new Numbers(N);
NumberGenerator ng1 = new NumberGenerator(numbers);
NumberGenerator ng2 = new NumberGenerator(numbers);
NumberGenerator ng3 = new NumberGenerator(numbers);
ng1.start();
ng2.start();
ng3.start();
}
}
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numbers) {
nums = numbers;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
nums.print();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public synchronized int getNum() {
return items.length;
}
public synchronized void set(int index, int x) {
items[index] = x;
}
public synchronized void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
I modified the getNum (), set(), and print() methods by adding the keyword synchronized because I think that in this way each thread can work on its own avoiding race condition.
java multithreading mvc observer-pattern
New contributor
$endgroup$
I have to:
1) Apply the Observer-Observable pattern to the original code.
2) starting from the original code, I have to suppose that the modification of the array fields (slot machine numbers) should be done in parallel by 3 NumberGenerator threads instead of just one.
My output seems to work fine but I'm wondering if my implemention is good enough or if am I doing something wrong. Could you tell me if my code is good or not?
ORIGINAL CODE:
import java.util.*;
public class SlotMachineApp {
private static final int N = 3;
public static void main(String args) {
Numbers numeri = new Numbers(N);
(new NumberGenerator(numeri)).start();
}
}
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numeri) {
nums = numeri;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
nums.print();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public int getNum() {
return items.length;
}
public void set(int index, int x) {
items[index] = x;
}
public void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
OBSERVER-OBSERVABLE IMPLEMENTATION:
Model:
package slot;
import static java.lang.Thread.sleep;
import java.util.Observable;
import java.util.Random;
public class Model extends Observable {
private static final int N = 3;
Numbers numbers = new Numbers(N);
NumberGenerator ng = new NumberGenerator(numbers);
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numbers) {
nums = numbers;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
setChanged();
notifyObservers();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public int getNum() {
return items.length;
}
public void set(int index, int x) {
items[index] = x;
}
public void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
}
View:
package slot;
import java.util.Observable;
import java.util.Observer;
public class View implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o != null && o instanceof Model) {
((Model) o).numbers.print();
}
}
}
Controller:
package slot;
public class Controller {
private Model model;
private View view;
public Controller(Model m, View v){
this.model = m;
this.view =v;
}
}
Main:
package slot;
public class Slot {
public static void main(String args) {
Model model = new Model();
View view = new View();
Controller controller = new Controller(model, view);
model.addObserver(view);
model.ng.start();
}
}
MVC is not required I just like to use it for practice! If I did something wrong even in the MVC I would like to know please! I know that my Controller is doing nothing but actually I don't know which method to put inside to let Model and View comunicate since Observer-Observable calls update() from model to view.
Thread - Implementation with 3 NumberGenerator:
import java.util.*;
public class SlotMachineApp {
private static final int N = 3;
public static void main(String args) {
Numbers numbers = new Numbers(N);
NumberGenerator ng1 = new NumberGenerator(numbers);
NumberGenerator ng2 = new NumberGenerator(numbers);
NumberGenerator ng3 = new NumberGenerator(numbers);
ng1.start();
ng2.start();
ng3.start();
}
}
class NumberGenerator extends Thread {
private Numbers nums;
public NumberGenerator(Numbers numbers) {
nums = numbers;
}
public void run() {
Random r = new Random();
for (int i = 1; i < 25; i++) {
int index = r.nextInt(nums.getNum());
nums.set(index, r.nextInt(5));
nums.print();
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
return;
}
}
}
}
class Numbers {
private final int items;
public Numbers(int n) {
items = new int[n];
}
public synchronized int getNum() {
return items.length;
}
public synchronized void set(int index, int x) {
items[index] = x;
}
public synchronized void print() {
for (int i = 0; i < items.length; i++) {
System.out.print(items[i] + "t");
}
System.out.println();
int i = 0;
while (i < items.length - 1 && items[i] == items[i + 1]) {
i++;
}
if (i >= items.length - 1) {
System.out.println("ALL EQUAL!!!!");
}
}
}
I modified the getNum (), set(), and print() methods by adding the keyword synchronized because I think that in this way each thread can work on its own avoiding race condition.
java multithreading mvc observer-pattern
java multithreading mvc observer-pattern
New contributor
New contributor
New contributor
asked 1 min ago
NoProgNoProg
11
11
New contributor
New contributor
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
NoProg is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212517%2fapplying-observer-observable-pattern-to-a-code-and-multithreading%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
NoProg is a new contributor. Be nice, and check out our Code of Conduct.
NoProg is a new contributor. Be nice, and check out our Code of Conduct.
NoProg is a new contributor. Be nice, and check out our Code of Conduct.
NoProg is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212517%2fapplying-observer-observable-pattern-to-a-code-and-multithreading%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown