IS480 Team wiki: 2016T1 Stark Mid Term Wiki

From IS480
Jump to navigation Jump to search
Team Stark Logo.png

Team Stark Home.png   HOME


Team Stark About Us.png   ABOUT US


Team Stark Project Overview.png   PROJECT OVERVIEW


Team Stark Project Management.png   PROJECT MANAGEMENT


Team Stark Documentation.png   DOCUMENTATION


Project Progress Summary

Midterm Slides: Download Here

MaiMai is deployed for production at http://app.maitwo.com
MaiMai is deployed for testing purpose 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

  • Live deployment and managed to get real users to use and comment. Feedback received were both positive and negative.
  • Many people (Testers, Real Users) who interact with MaiMai mistaken MaiMai as a "Marketplace" platform instead of a "Transaction" platform.
  • Performed UT2 with 38 users. Feedback was largely positive and also very helpful.
  • Added in plans to further structure agreements,e.g "Location Check-in" into our project scope after receiving feedback during acceptance.
  • Realized that high possibility that banks lack notification services for personal savings accounts

Project Management

Project Scope

Stark Scope before.png
Stark Scope midterm wiki.png

Project Timeline

Stark schedule before.png
Stark schedule after.png

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

Stark SM midterm.png

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.


View our Schedule Metrics Here!

Bug Metrics

Stark BM midterm wiki.png

Iteration Bug Score Bug Summary Action Taken
6 43

3 low
8 high
0 critical

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
21 high
3 critical

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
3 high
2 critical

The first critical bug was system crashed when a dispute for review is filed. The second critical bug was images is not updated when listing image name is being edited. Resolve bugs immediately. No major delay was caused. Critical bug did not occur again. Similar action was performed but bug did not replicate.

Viewed our Bug Metrics Here!

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.
2. Look into emulating industry standards and follow what others are doing.

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).

Uploadimage1.png Uploadimage2.png

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

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) {
     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
Real time.png

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()
   "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) {
     } else if (Object.keys(listing).length > 0) {

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':
        case 'edit':
           contentEdited.push(pendingAgreement(agreement, 'edit', owner === myUser));
        case 'delete':
           contentEdited.push(pendingAgreement(agreement, 'delete', owner === myUser));

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':
                   <UserMessage key={id} message={content} date={date} owner={owner === user} username={user}/>
           case 'system':
                   <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”
S-ui.PNG S-ui2.PNG

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 className="ui secondary menu stackable">
      <div className="right menu">
          {this.props.isMobile ? "" : withdrawButton}

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
Design Low-Fi Prototype
High-Fi Prototype
UI Prototype
Testing User Testing 1 User Test 1
User Test 2


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


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 but in fact sponsors, in the form of our users, who used our app and gave feedback. But because they're all individuals the opinions are too varied. This poses another challenge and we have to make the final decision. 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

Name Reflections
Stark Ivy.png

Lee Chian Yee

As the PM, I learnt how to manage expectations from various stakeholders such as Supervisor, Mentor, and most importantly, my teammates. In addition, I also learnt how to manage changes to the project scope and scheduling it to fit into the timeline according to their priority.

Stark Hem.png

Raji Hemanth Kumar

From the time of acceptance, I have managed to understand the difficulty of getting traction for the application. I have understood the importance of effective communication with potential users, especially in the case of cold-selling. I have also understood the difficult marketing processes available on social media, how to execute them in an effective manner to garner attention from the public.

Stark Qx.png

Lee Qixian

Coming up with the system and application is hard. Getting real users is even harder. However, hearing the comments, be it positive or negative, from real users is extremely satisfying.

STARK Josh.png

Phua Xue Yong

Since acceptance till midterms, i’ve learned how to weather through my workload to ensure that we continue to stay on track despite the overwhelming workload from both FYP and my other modules. I’ve learnt to understand the need for teamwork to support and encourage one another when deadlines seems overwhelming.

Stark Qp.png

Lin Qianpin

I have learnt that software estimation is more difficult than expected, both in terms of estimating the time and effort required for front end changes. Now I also better understand and appreciate the need for User Testings and thorough analysis.

Stark Darren.png

Darren Tay Kuang Yong

I have learnt how to manage my expectations as they usually don’t add up to reality. I’ve learnt how to appreciate my group mates more as they carry me through the difficult tasks I’ve encountered and helping to cover for me when the going is really tough. For that, I’m always grateful and more appreciative of the people I have around me.