Difference between revisions of "IS480 Team wiki: 2016T1 Stark Mid Term Wiki"
Cylee.2013 (talk | contribs) |
Cylee.2013 (talk | contribs) |
||
Line 54: | Line 54: | ||
<font size=4><b>Midterm Slides</b>: </font> | <font size=4><b>Midterm Slides</b>: </font> | ||
<br><br> | <br><br> | ||
+ | *MaiMai is live at http://app.maitwo.com | ||
+ | *MaiMai is deployed for production at http://uat.maitwo.com | ||
+ | *Learn more about us at http://www.maitwo.com | ||
+ | |||
<b>Current Iteration:</b> 12 <br/> | <b>Current Iteration:</b> 12 <br/> | ||
<b>Total Iterations:</b> 16 <br/> | <b>Total Iterations:</b> 16 <br/> | ||
Line 579: | Line 583: | ||
<h2>Deployment</h2> | <h2>Deployment</h2> | ||
− | *MaiMai is deployed | + | *MaiMai is live at http://app.maitwo.com |
+ | *MaiMai is deployed for production at http://uat.maitwo.com | ||
*Learn more about us at http://www.maitwo.com. | *Learn more about us at http://www.maitwo.com. | ||
Revision as of 21:34, 5 October 2016
Project Progress Summary
Midterm Slides:
- MaiMai is live at http://app.maitwo.com
- MaiMai is deployed for production at http://uat.maitwo.com
- Learn more about us at http://www.maitwo.com
Current Iteration: 12
Total Iterations: 16
Iteration Dates: 26 Sep 2016 - 9 Oct 2016
- Overall Project Progress: 85%
- Modules To-Be Done - Good-To-Have feature: Dispute System & Manage Dispute (Admin): 3-way chat
- Modules To-Be Done - Good-To-Have feature: Listing: Export to forum/share on social media
- Modules To-Be Done - Good-To-Have feature: Chat: Location Check-In
- Modules To-Be Done - Good-To-Have feature: Payment: iBanking
- Modules Completed: Accounts, Review/Rating, View Pending Checkout (Admin). Payment (Credit Card)
- Team Stark is confident of completing all modules up till tertiary functions with an additional good to have function
- Web application fully deployed
Project Highlights
- Many people (Testers, Real Users) who interact with MaiMai mistaken MaiMai as a "Marketplace" platform instead of a "Transaction" platform.
- Added in "Location Check-in" into our project scope after receiving feedback during acceptance.
- Banks do not provide automated notification service when account is being credited.
Project Management
Project Scope
Planned |
---|
Actual |
---|
Project Timeline
Planned |
---|
Actual |
---|
Project Status
Module | Status | Confident Level (0-1) | Comment |
---|---|---|---|
Account | 100% | 1 | Fully deployed and tested. |
Listing | 100% | 1 | "Exporting to external media" is scheduled to be completed by iteration 12 |
Chat | 100% | 1 | "Location Check-in" is scheduled to be completed by iteration 13 |
Review/Rating | 100% | 1 | Fully deployed and tested. |
Dispute System | 100% | 1 | "3-way chat" is scheduled to be completed by iteration 12 |
Manage Dispute (Admin) | 100% | 1 | "3-way chat" is scheduled to be completed by iteration 12 |
Manage Data (Admin) | 100% | 1 | Fully deployed and tested. |
View Pending Checkout (Admin) | 100% | 1 | Fully deployed and tested. |
Payment (Credit Card) | 100% | 1 | Fully deployed and tested. |
Payment (iBanking) | 90% | 0.9 | The possible lack of notification service provided by bank and thus a lack of automated system. |
View our Project Timeline Here!
Schedule Highlights
The following changes has been made to our project scope and reflected in our schedule.
- "3 way chat" was shifted from iteration 9 to iteration 12.
- "Location Check In" was added into iteration 13.
- UT3 was rescheduled from 14 Oct to 24 Oct.
- Added in Good to Have functions. These are functions which we may consider to develop during IS480.
- Good to Have - "3 way chat" was shifted from secondary function. "Location Check In" feature was added to scope.
Refer to our Change Management for more!
Project Metrics
Schedule Metrics
Iteration | Planned Duration (Days) | Actual Duration (Days) | Schedule Metric Score | Action Taken | Status |
---|---|---|---|---|---|
8 | 14 | 16 | 0.88 | More time needed to fix bugs from UT1 and after the integration of Dispute Management.
Follow up action: Informed supervisor and mentor about the delay. More hours put in for debugging. No major delay to overall schedule. |
Completed |
View our Schedule Metrics Here!
Bug Metrics
Iteration | Bug Score | Bug Summary | Action Taken |
---|---|---|---|
6 | 43 3 low |
The spike in bug count is due to the integration of dispute management system together with previous completed features. | Resolve bugs immediately. No major delay was caused. |
8 | 179 44 low |
The spike in bug count is because of the integration of many new features together for UT1. | Resolve bugs immediately. Iteration 8 was scheduled for post UT1 debugging. PM scheduled the Lead Backend developer to focus on debugging while the rest of the developers focus on development. |
9 | 42 7 low |
Resolve bugs immediately. No major delay was caused. Critical bug did not occur again. Similar action was performed but bug did not replicate. |
Project Risks
Risk Description | Likelihood | Impact | Mitigation Strategy |
---|---|---|---|
Lack of automated notification avenues by banks | High | High Lack of credit notification control or automation due to bank not releasing their API and having to rely on their existing notification system |
1. Check all the credit transactions manually. 2. Drop "ibanking" function as last resolution. |
Mismatch of product against market. | High | High Developed product may not be what our target users or anyone in the market wants. |
1. Gather more feedbacks during testing to validate market needs against project idea. 2. Transact with more real user and conduct interview with them to understand the problems and needs of the market. |
Quick rise of direct competition | Low | Low Existing application like Caurosell can easily implement payment services that we are providing. |
We provide user with dispute management service which is something that is unique to us and we are investing our resources into defining a stringent and reliable process of micro management. As such we have the upper hand because that is our prime feature. However, it still remain as a risk. |
Lack of knowledge in system security and architecture | Low | High Project may be potentially delayed due to time spent on learning. Initial stability of application may be affected as there may be more bugs. |
The likelihood of risk occurring has been lowered from High (during Acceptance stage) to Low as developers are more familiar with the security and architecture.
1. Seek help from supervisor or professors in the relevant fields. |
Mentor/Supervisor might be unavailable for weekly meeting | Low | Low Mentor/supervisor may have work and other meetings to attends thus unable to keep them updated with project status and clarify our doubts. |
1. Postpone meeting and meet contact whenever nearest time possible 2. Video conference meeting |
Technical Complexity
Complexities arise due to the following needs:
- User Experience
- Performance (Client and Server)
- Compatibility across devices and browsers
- Mobile vs Desktop
Processing of Users’ Uploaded Images
Problem: Beforehand we had a “limit” on the size of images to 1MB
- Server resources
- Faster loading for users
Causes: Poor user experience
- Users complain why other “apps” out there that can accept all images from their phones (main basis of benchmarking).
Benchmark max file size to accept:
- Two “best” phones (iPhone 7s and Samsung Galaxy 7 camera captured photos (12 MP 3-6 MB)
Keep file sizes after processing below 1MB
- Maintaining sufficient quality for the web
Processing to be done client side
- If image processing is to be at server side there is an additional two way transfer of the user uploading to the server and downloading the processed image
- Heavy on server resources
What we did:
- Used HTML’s Canvas for resizing
- Client-side library Pica for reducing image quality
Explaination:
1. Retrieve images from form
2. Create HTML Image object
3. Load uploaded image into Image object
//Goes through the images ( might have multiple images at one go) let images = this.state.image; for (let i = 0; i < images.length; i++) { let image = images[i]; let img = new Image(); img.src = window.URL.createObjectURL(image); img.onload = () => {
4. Create a HTML Canvas object
5. Draw Image object onto Canvas
img.onload = () => { let src = document.createElement('canvas'); src.width = img.width; src.height = img.height; let ctx = src.getContext('2d'); ctx.drawImage(img, 0, 0);
6. Determine processed Canvas size while maintaining ratio
let dest = document.createElement('canvas'); let longerLength = 1536; let shorterLength = 1180; let ratio; if ((src.width > src.height || src.width === src.height) && (src.width > longerLength || src.height > shorterLength)) { if (src.width / longerLength > 1) { ratio = longerLength / src.width; dest.width = Math.round(ratio * src.width); dest.height = Math.round(ratio * src.height); } else { ratio = src.width / longerLength; dest.height = Math.round(ratio * src.height); dest.width = Math.round(ratio * src.width); }
7. Use Pica to do image optimization from source Canvas to destination Canvas
pica.resizeCanvas(src, dest, (err) => { if (err) { console.log(err); return; } dest.toBlob(processImage, 'image/jpeg', 0.8); });
8. With processed Canvas ready, we convert it into a blob and then into a Buffer Object to transfer to backend later
const processImage = (blob) => { const data = (file) => { let reader = new FileReader(); let name = file.name; reader.onloadend = (e) => { let results = this.state.uploadData; let sha1 = this.state.sha1; let image = reader.result; let buffer = new Buffer(image.byteLength); let view = new Uint8Array(image); for (let i = 0; i < buffer.length; ++i) { buffer[i] = view[i]; }
9. We later realized that iOS browsers do not support the Canvas function “toBlob”
export const addToBlobFunction = function () { // add toBlob functionality for browsers that do not support it. if( !HTMLCanvasElement.prototype.toBlob ) { Object.defineProperty( HTMLCanvasElement.prototype, 'toBlob', { value: function( callback, type, quality ) { const bin = atob( this.toDataURL( type, quality ).split(',')[1] ), len = bin.length, len32 = len >> 2, a8 = new Uint8Array( len ), a32 = new Uint32Array( a8.buffer, 0, len32 ); for( var i=0, j=0; i < len32; i++ ) { a32[i] = bin.charCodeAt(j++) | bin.charCodeAt(j++) << 8 | bin.charCodeAt(j++) << 16 | bin.charCodeAt(j++) << 24; } let tailLength = len & 3; while( tailLength-- ) { a8[ j ] = bin.charCodeAt(j++); }
End Result: Image sizes reduced from (5.5MB to 0.4MB, 8% of original image size)
Reactive and Real-time Chat
The chat serves as the core foundation to the transaction process for buyers and sellers Its’ main purpose is to facilitate efficient and effective communication and transaction between users. It needed to be reactive and real-time:
- Needs to respond to changes by either user especially when building up the initial agreements
- Needs to reflect proper status and relevant information according to the stage in the transaction
Reactivity and Real-Time achieved with Meteor and React:
- Meteor provide the real time syncing
- React allows us to react to changes in data
Designing of the data “schemas” is especially important Required to allow for changes to be properly reflected Caters to a publish-subscribe methodology
let toInsert = { "_id": chatId, "listing": listingId, "listingOwner": listingOwner, "otherUser": otherUser, "status": "open", "price": listing.price, "agreements": agreements, "privateImages": {}, createdAt: new Date() }; Chats.insert(toInsert);
Messages.insert({ "chat": chatId, "owner": username, "type": "user", "message": message, "createdAt": new Date() })
case 'add': if (currentAgreement) throw new Meteor.Error('agreement already exists'); agreements[agreement] = { agreement: agreement, owner: username, status: 'add' };
Using Meteor for data subscription, data changes are continuously pushed to the React Component
export default createContainer(({params}) => { // … const chatHandle = Meteor.subscribe('getChat', chatId, { // … }); // … }, Conversation);
componentWillReceiveProps(nextProps) { let {user, chat, transaction, payment} = nextProps;
Using React’s lifecycle management (componentWillReceiveProps), we respond to changes whenever it receives new data
componentWillReceiveProps(nextProps) { let chat = nextProps.chat; let listing = nextProps.listing; if (Object.keys(chat).length > 0) { this.setDetails(chat); } else if (Object.keys(listing).length > 0) { this.setListingDetails(listing); }}
For example rendering the agreements and the available actions
agreements.forEach((val) => { let agreement = val.agreement; let owner = val.owner; let status = val.status; switch (status) { case 'confirmed': contentConfirmed.push(confirmedAgreement(agreement)); break; case 'edit': contentEdited.push(pendingAgreement(agreement, 'edit', owner === myUser)); break; case 'delete': contentEdited.push(pendingAgreement(agreement, 'delete', owner === myUser)); break;
Or showing new chat messages immediately
getMessage(messageArr) { let user = this.props.myUser; let messages = []; messageArr.map((message) => { let {_id: id, owner, type, message: content, createdAt: date} = message; switch (type) { case 'user': messages.push( <UserMessage key={id} message={content} date={date} owner={owner === user} username={user}/> ); break; case 'system': messages.push( <SystemMessage key={id} message={content} date={date}
Universal Web App (Mobile and Desktop)
Currently, MaiMai does not have any native apps for mobile devices.
As such, we needed to cater to browsers of all sizes
Semantic-UI is responsive but not fully “mobile friendly”
1. Added a listener to the browser’s innerWidth
- “Width (in pixels) of the browser window viewport including, if rendered, the vertical scrollbar.”
const handleResize = () => { window.innerWidth <= 560 ? this.setState({mobile: true}) : this.setState({mobile: false}); };
window.addEventListener('resize', this.state.handleResize);
const childrenWithProps = React.Children.map(this.props.children, (child) => React.cloneElement(child, { user: this.props.user, isMobile: this.state.mobile }) );
2. Using our own isMobile prop, we respond to various browser widths
<div className="ui secondary pointing menu stackable" id="viewPaymentsMenu"> //… {!this.props.isMobile ? "" : withdrawButton} </div> <div className="ui secondary menu stackable"> <div className="right menu"> {this.props.isMobile ? "" : withdrawButton} //… </div> </div>
Final Outcome:
Quality of Product
Intermediate Deliverables
Stage | Specification | Modules |
---|---|---|
Project Requirements | Market Research | Market Research |
Project Management | Minutes | Minutes |
Metrics | Schedule Metrics Bug Metrics | |
Risk | Risks | |
Change Management | Change Management | |
Diagrams | Use Diagrams Architecture Diagram |
Diagrams |
Design | Low-Fi Prototype High-Fi Prototype |
UI Prototype |
Testing | User Testing 1 | User Test 1 User Test 2 |
Deployment
- MaiMai is live at http://app.maitwo.com
- MaiMai is deployed for production at http://uat.maitwo.com
- Learn more about us at http://www.maitwo.com.
User Testing
User Testing | Date | Venue | Users | Link |
---|---|---|---|---|
User Testing 1 | 1st August 2016 - 8th August 2016 | Off-Site (At respective members' discretion) | 22 | User Testing 1 |
User Testing 2 | 12th September 2016 - 26th September 2016 | SIS GSR 2-7 & Off-Site (At respective members' discretion) | 38 | User Testing 2 |
Reflection
Team Reflection It has been a tough but great learning journey for Team STARK. We learnt to complement each others' strength and weaknesses which thus helps to provide quality work. As a self-proposed project, we felt that the most challenging aspect is that we do not have a sponsor to provide us a specific project scope. Therefore, we have to take full ownership for both business and functional requirements. We learnt that apart from focusing on development of application, market research plays a very important role in ensuring that the final product is well-needed in the real world.
Individual Reflection