Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
samluescher committed Sep 15, 2012
0 parents commit 43d1cb1
Show file tree
Hide file tree
Showing 48 changed files with 2,160 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .gitignore
@@ -0,0 +1,14 @@
.DS_Store
*~

build/

*.pbxuser
*.perspective
*.perspectivev3

*.mode1v3
*.mode2v3

xcuserdata/

972 changes: 972 additions & 0 deletions GeoSenseReliefClientAR.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions Project.xcconfig
@@ -0,0 +1,14 @@
//THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT.
//THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED
OF_PATH = ../../..

//THIS HAS ALL THE HEADER AND LIBS FOR OF CORE
#include "../../../libs/openFrameworksCompiled/project/ios/CoreOF.xcconfig"

OTHER_LDFLAGS = $(OF_CORE_LIBS)
HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS)

COMPRESS_PNG_FILES = NO
GCC_THUMB_SUPPORT = NO
IPHONEOS_DEPLOYMENT_TARGET = 3.1
TARGETED_DEVICE_FAMILY = 1
Empty file added bin/data/.gitkeep
Empty file.
Binary file added bin/data/Default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added bin/data/Icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions bin/data/json/earthquakes.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions bin/data/json/reactors.json
@@ -0,0 +1 @@
{"fullCount":442,"originalCount":21,"maxCount":2,"gridSize":0.08888888890126231,"items":[{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1982-01-01T00:00:00.000Z","min":"1982-01-01T00:00:00.000Z"},"loc":[141.024,37.3153],"label":{"max":"Fukushima-Daini-1 (JP)","min":"Fukushima-Daini-1 (JP)"}},{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1985-01-01T00:00:00.000Z","min":"1985-01-01T00:00:00.000Z"},"loc":[138.598,37.434],"label":{"max":"Kashiwazaki Kariwa-1 (JP)","min":"Kashiwazaki Kariwa-1 (JP)"}},{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1990-01-01T00:00:00.000Z","min":"1990-01-01T00:00:00.000Z"},"loc":[138.598,37.4335],"label":{"max":"Kashiwazaki Kariwa-2 (JP)","min":"Kashiwazaki Kariwa-2 (JP)"}},{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1993-01-01T00:00:00.000Z","min":"1993-01-01T00:00:00.000Z"},"loc":[138.598,37.433],"label":{"max":"Kashiwazaki Kariwa-3 (JP)","min":"Kashiwazaki Kariwa-3 (JP)"}},{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1994-01-01T00:00:00.000Z","min":"1994-01-01T00:00:00.000Z"},"loc":[138.598,37.4325],"label":{"max":"Kashiwazaki Kariwa-4 (JP)","min":"Kashiwazaki Kariwa-4 (JP)"}},{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1990-01-01T00:00:00.000Z","min":"1990-01-01T00:00:00.000Z"},"loc":[138.598,37.432],"label":{"max":"Kashiwazaki Kariwa-5 (JP)","min":"Kashiwazaki Kariwa-5 (JP)"}},{"val":{"avg":1315,"sum":1315,"max":1315,"min":1315},"altVal":[],"count":1,"datetime":{"max":"1996-01-01T00:00:00.000Z","min":"1996-01-01T00:00:00.000Z"},"loc":[138.598,37.4315],"label":{"max":"Kashiwazaki Kariwa-6 (JP)","min":"Kashiwazaki Kariwa-6 (JP)"}},{"val":{"avg":1315,"sum":1315,"max":1315,"min":1315},"altVal":[],"count":1,"datetime":{"max":"1997-01-01T00:00:00.000Z","min":"1997-01-01T00:00:00.000Z"},"loc":[138.598,37.431],"label":{"max":"Kashiwazaki Kariwa-7 (JP)","min":"Kashiwazaki Kariwa-7 (JP)"}},{"val":{"avg":1056,"sum":1056,"max":1056,"min":1056},"altVal":[],"count":1,"datetime":{"max":"1978-01-01T00:00:00.000Z","min":"1978-01-01T00:00:00.000Z"},"loc":[140.614,36.4664],"label":{"max":"Tokai-2 (JP)","min":"Tokai-2 (JP)"}},{"val":{"avg":796,"sum":796,"max":796,"min":796},"altVal":[],"count":1,"datetime":{"max":"2002-01-01T00:00:00.000Z","min":"2002-01-01T00:00:00.000Z"},"loc":[141.504,38.401],"label":{"max":"Onagawa-3 (JP)","min":"Onagawa-3 (JP)"}},{"val":{"avg":796,"sum":796,"max":796,"min":796},"altVal":[],"count":1,"datetime":{"max":"1995-01-01T00:00:00.000Z","min":"1995-01-01T00:00:00.000Z"},"loc":[141.504,38.4005],"label":{"max":"Onagawa-2 (JP)","min":"Onagawa-2 (JP)"}},{"val":{"avg":498,"sum":498,"max":498,"min":498},"altVal":[],"count":1,"datetime":{"max":"1984-01-01T00:00:00.000Z","min":"1984-01-01T00:00:00.000Z"},"loc":[141.504,38.4],"label":{"max":"Onagawa-1 (JP)","min":"Onagawa-1 (JP)"}},{"val":{"avg":760,"sum":760,"max":760,"min":760},"altVal":[],"count":1,"datetime":{"max":"1978-01-01T00:00:00.000Z","min":"1978-01-01T00:00:00.000Z"},"loc":[141.034,37.4217],"label":{"max":"Fukushima-Daiichi-4 (JP)","min":"Fukushima-Daiichi-4 (JP)"}},{"val":{"avg":760,"sum":760,"max":760,"min":760},"altVal":[],"count":1,"datetime":{"max":"1976-01-01T00:00:00.000Z","min":"1976-01-01T00:00:00.000Z"},"loc":[141.033,37.4217],"label":{"max":"Fukushima-Daiichi-3 (JP)","min":"Fukushima-Daiichi-3 (JP)"}},{"val":{"avg":760,"sum":760,"max":760,"min":760},"altVal":[],"count":1,"datetime":{"max":"1974-01-01T00:00:00.000Z","min":"1974-01-01T00:00:00.000Z"},"loc":[141.032,37.4217],"label":{"max":"Fukushima-Daiichi-2 (JP)","min":"Fukushima-Daiichi-2 (JP)"}},{"val":{"avg":913.5,"sum":1827,"max":1067,"min":760},"altVal":[],"count":2,"datetime":{"max":"1979-01-01T00:00:00.000Z","min":"1978-01-01T00:00:00.000Z"},"loc":[141.031,37.429],"label":{"max":"Fukushima-Daiichi-6 (JP)","min":"Fukushima-Daiichi-5 (JP)"}},{"val":{"avg":439,"sum":439,"max":439,"min":439},"altVal":[],"count":1,"datetime":{"max":"1971-01-01T00:00:00.000Z","min":"1971-01-01T00:00:00.000Z"},"loc":[141.031,37.4217],"label":{"max":"Fukushima-Daiichi-1 (JP)","min":"Fukushima-Daiichi-1 (JP)"}},{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1987-01-01T00:00:00.000Z","min":"1987-01-01T00:00:00.000Z"},"loc":[141.027,37.3153],"label":{"max":"Fukushima-Daini-4 (JP)","min":"Fukushima-Daini-4 (JP)"}},{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1985-01-01T00:00:00.000Z","min":"1985-01-01T00:00:00.000Z"},"loc":[141.026,37.3153],"label":{"max":"Fukushima-Daini-3 (JP)","min":"Fukushima-Daini-3 (JP)"}},{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1984-01-01T00:00:00.000Z","min":"1984-01-01T00:00:00.000Z"},"loc":[141.025,37.3153],"label":{"max":"Fukushima-Daini-2 (JP)","min":"Fukushima-Daini-2 (JP)"}}]}
1 change: 1 addition & 0 deletions bin/data/json/safecast.6.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions bin/data/json/safecast.json

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions bin/data/json/test.json
@@ -0,0 +1,10 @@
{"fullCount":442,"originalCount":21,"maxCount":2,"gridSize":1,"items":[

{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1982-01-01T00:00:00.000Z","min":"1982-01-01T00:00:00.000Z"},"loc":[128,28],"label":{"max":"Fukushima-Daini-1 (JP)","min":"Fukushima-Daini-1 (JP)"}},
{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1982-01-01T00:00:00.000Z","min":"1982-01-01T00:00:00.000Z"},"loc":[130,30],"label":{"max":"Fukushima-Daini-1 (JP)","min":"Fukushima-Daini-1 (JP)"}},
{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1982-01-01T00:00:00.000Z","min":"1982-01-01T00:00:00.000Z"},"loc":[132,32],"label":{"max":"Fukushima-Daini-1 (JP)","min":"Fukushima-Daini-1 (JP)"}},
{"val":{"avg":1067,"sum":1067,"max":1067,"min":1067},"altVal":[],"count":1,"datetime":{"max":"1982-01-01T00:00:00.000Z","min":"1982-01-01T00:00:00.000Z"},"loc":[150,46],"label":{"max":"Fukushima-Daini-1 (JP)","min":"Fukushima-Daini-1 (JP)"}}



]}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added bin/data/qcar_assets/StonesAndChips.dat
Binary file not shown.
7 changes: 7 additions & 0 deletions bin/data/qcar_assets/StonesAndChips.xml
@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<QCARConfig xsi:noNamespaceSchemaLocation="qcar_config.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Tracking>
<ImageTarget name="stones" size="247 173"/>
<ImageTarget name="chips" size="247 173"/>
</Tracking>
</QCARConfig>
Binary file added bin/data/qcar_assets/Tarmac.dat
Binary file not shown.
6 changes: 6 additions & 0 deletions bin/data/qcar_assets/Tarmac.xml
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<QCARConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="qcar_config.xsd">
<Tracking>
<ImageTarget size="320 224" name="tarmac" />
</Tracking>
</QCARConfig>
Binary file added bin/data/qcar_assets/TextureTeapotBrass.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions iPhone_Prefix.pch
@@ -0,0 +1,8 @@
//
// Prefix header for all source files of the 'iPhone' target in the 'iPhone' project
//

#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#endif
Binary file added markers/chips.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added markers/stones.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added markers/target_chips_A4.pdf
Binary file not shown.
Binary file added markers/target_chips_USLetter.pdf
Binary file not shown.
Binary file added markers/target_stones_A4.pdf
Binary file not shown.
Binary file added markers/target_stones_USLetter.pdf
Binary file not shown.
Binary file added markers/target_tarmac_A4.pdf
Binary file not shown.
Binary file added markers/target_tarmac_USLetter.pdf
Binary file not shown.
Binary file added markers/tarmac.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions ofxiphone-Info.plist
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_NAME:identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationExitsOnSuspend</key>
<false/>
<key>UIInterfaceOrientation</key>
<string>UIInterfaceOrientationPortrait</string>
<key>UIStatusBarHidden</key>
<true/>
</dict>
</plist>
95 changes: 95 additions & 0 deletions src/ImageMesh.h
@@ -0,0 +1,95 @@
#include "ofMain.h"

/*
This code demonstrates the difference between using an ofMesh and an ofVboMesh.
The ofMesh is uploaded to the GPU once per frame, while the ofVboMesh is
uploaded once. This makes it much faster to draw multiple copies of an
ofVboMesh than multiple copies of an ofMesh.
*/

/*
These functions are for adding quads and triangles to an ofMesh -- either
vertices, or texture coordinates.
*/
//--------------------------------------------------------------
void addFace(ofMesh& mesh, ofVec3f a, ofVec3f b, ofVec3f c) {
mesh.addVertex(a);
mesh.addVertex(b);
mesh.addVertex(c);
}

//--------------------------------------------------------------
void addFace(ofMesh& mesh, ofVec3f a, ofVec3f b, ofVec3f c, ofVec3f d) {
addFace(mesh, a, b, c);
addFace(mesh, a, c, d);
}

//--------------------------------------------------------------
void addTexCoords(ofMesh& mesh, ofVec2f a, ofVec2f b, ofVec2f c) {
mesh.addTexCoord(a);
mesh.addTexCoord(b);
mesh.addTexCoord(c);
}

//--------------------------------------------------------------
void addTexCoords(ofMesh& mesh, ofVec2f a, ofVec2f b, ofVec2f c, ofVec2f d) {
addTexCoords(mesh, a, b, c);
addTexCoords(mesh, a, c, d);
}

/*
The 3d data is stored in an image where alpha represents depth. Here we create
a 3d point from the current x,y image position.
*/
//--------------------------------------------------------------
ofVec3f getVertexFromImg(ofImage& img, int x, int y, float maxHeight) {
ofColor color = img.getColor(x, y);
if(color.a > 0) {
float z = ofMap(color.r, 0, 255, 0, maxHeight);
return ofVec3f(x - img.getWidth() / 2, -y + img.getHeight() / 2, z);
} else {
return ofVec3f(0, 0, 0);
}
}

//--------------------------------------------------------------
ofMesh meshFromImage(ofImage& img, int skip, float maxHeight) {
ofMesh mesh;
// OF_PRIMITIVE_TRIANGLES means every three vertices create a triangle
mesh.setMode(OF_PRIMITIVE_TRIANGLES);
int width = img.getWidth();
int height = img.getHeight();
int numFaces;
float ws = width;
float hs = height;
ofVec3f zero(0, 0, 0);
for(int y = 0; y < height - skip; y += skip) {
for(int x = 0; x < width - skip; x += skip) {
/*
To construct a mesh, we have to build a collection of quads made up of
the current pixel, the one to the right, to the bottom right, and
beneath. These are called nw, ne, se and sw. To get the texture coords
we need to use the actual image indices.
*/
ofVec3f nw = getVertexFromImg(img, x, y, maxHeight);
ofVec3f ne = getVertexFromImg(img, x + skip, y, maxHeight);
ofVec3f sw = getVertexFromImg(img, x, y + skip, maxHeight);
ofVec3f se = getVertexFromImg(img, x + skip, y + skip, maxHeight);

ofVec2f nwi(x / ws, y / hs);
ofVec2f nei((x + skip) / ws, y / hs);
ofVec2f swi(x / ws, (y + skip) / hs);
ofVec2f sei((x + skip) / ws, (y + skip) / hs);

// ignore any zero-data (where there is no depth info)
if(nw != zero && ne != zero && sw != zero && se != zero) {
addFace(mesh, nw, ne, se, sw);
addTexCoords(mesh, nwi, nei, sei, swi);
numFaces += 1;
}
}
}

cout << "generated mesh with faces: " << numFaces << "\n ";
return mesh;
}
20 changes: 20 additions & 0 deletions src/MapFeature.cpp
@@ -0,0 +1,20 @@
//
// MapFeature.cpp
//
// Created by Samuel Lüscher on 7/27/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include "MapFeature.h"

void MapFeature::customDraw() {
ofVec3f pos = getPosition();
ofPushMatrix();
ofTranslate(-pos);
setScale(width, width, height);
ofFill();
ofSetColor(min(normVal * 255, 255.0f), 128, 200, 255);
ofTranslate(0, 0, 0.5);
ofBox(1);
ofPopMatrix();
}
19 changes: 19 additions & 0 deletions src/MapFeature.h
@@ -0,0 +1,19 @@
//
// MapFeature.h
//
// Created by Samuel Lüscher on 7/27/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include "ofMain.h"

class MapFeature: public ofNode {

public:
float normVal;
float width;
float height;
ofColor color;

void customDraw();
};
65 changes: 65 additions & 0 deletions src/MouseController.cpp
@@ -0,0 +1,65 @@
#include "MouseController.h"

#define MAP_MOVE_INC 0.1f
#define VELOCITY_DECAY 0.15
#define EASING_TIME 2.0f

MouseController::MouseController() {
ofAddListener(ofEvents().keyPressed,this,&MouseController::keyPressed);
ofRegisterMouseEvents(this);
}

//--------------------------------------------------------------
void MouseController::update(ofCamera * camera) {
dragVelocity *= 1-(VELOCITY_DECAY);
float scaled = ofMap(ofGetElapsedTimef(),easeStartTime,easeStartTime+EASING_TIME,1,0,1);
camera->move(dragVelocity*ofxEasingFunc::Quad::easeOut(scaled));
}

void MouseController::keyPressed(ofKeyEventArgs & args){
switch (args.key) {
case 356:
dragVelocity.set(MAP_MOVE_INC,0,0);
easeStartTime = ofGetElapsedTimef();
break;
case 357:
dragVelocity.set(0,0,MAP_MOVE_INC);
easeStartTime = ofGetElapsedTimef();
break;
case 358:
dragVelocity.set(-MAP_MOVE_INC,0,0);
easeStartTime = ofGetElapsedTimef();
break;
case 359:
dragVelocity.set(0,0,-MAP_MOVE_INC);
easeStartTime = ofGetElapsedTimef();
break;
};
}

//--------------------------------------------------------------
void MouseController::mouseDragged(ofMouseEventArgs & args){
if(args.button == 0) {
dragVelocity = (ofVec3f(args.x,args.y,0)-previousMousePosition)*0.01;
dragVelocity.x = -dragVelocity.x;
} if(args.button == 2) {
dragVelocity.z += (args.y - previousMousePosition.y)*0.001;
}

easeStartTime = ofGetElapsedTimef();
previousMousePosition.set(args.x,args.y,0);
}

//--------------------------------------------------------------
void MouseController::mousePressed(ofMouseEventArgs & args){
previousMousePosition.set(args.x,args.y,0);
}

void MouseController::mouseReleased(ofMouseEventArgs & args){

}

void MouseController::mouseMoved(ofMouseEventArgs & args){

}

23 changes: 23 additions & 0 deletions src/MouseController.h
@@ -0,0 +1,23 @@
#pragma once

#include "ofMain.h"
#include "ofxEasingFunc.h"
#include "ofEvents.h"
#include "SceneController.h"

//--------------------------------------------------------
class MouseController : public SceneController{
public:
MouseController();
void keyPressed(ofKeyEventArgs & args);
void mouseMoved(ofMouseEventArgs & args);
void mouseDragged(ofMouseEventArgs & args);
void mousePressed(ofMouseEventArgs & args);
void mouseReleased(ofMouseEventArgs & args);
void update(ofCamera* camera);

float easeStartTime;
ofVec3f previousMousePosition;
ofVec3f dragVelocity;
};

24 changes: 24 additions & 0 deletions src/QCARController.h
@@ -0,0 +1,24 @@
#pragma once

#include "ofMain.h"
#include "ofxEasingFunc.h"
#include "ofEvents.h"
#include "SceneController.h"
#include "ofxQCAR.h"

//--------------------------------------------------------
class QCARController : public SceneController{
public:
QCARController();
void touchDown(ofTouchEventArgs & touch);
void touchMoved(ofTouchEventArgs & touch);
void touchUp(ofTouchEventArgs & touch);
void touchDoubleTap(ofTouchEventArgs & touch);
void touchCancelled(ofTouchEventArgs & touch);
void update(ofCamera* camera);

float easeStartTime;
ofVec3f previousMousePosition;
ofVec3f dragVelocity;
};

0 comments on commit 43d1cb1

Please sign in to comment.