#台云integration#SHOW out your meta-service#boringmathematics

1. Why is there boring mathematics

No matter what the reason is, people’s time is becoming more and more fragmented, and even more so, the fragmentation of time has become the normal life of some people. Sporadic time fragments often make people feel bored. Apart from mindlessly watching short videos, can you do something more clever? For example, think, even think deeply! After all, the more a person’s brain is used, the smarter it becomes, and the less it is used, the more rusty it becomes. Philosopher and thinker Bacon once said, “Mathematics is the gymnastics of thinking.” In the fragmented time, solving two math problems and using your brain should be a good way to live up to the time. Then develop a mobile application to meet this original intention. If you want to play with mathematics during your boring time, this application is called Boring Mathematics.

Sublimating it further, the value proposition and original intention of “Boring Mathematics” are very simple:

Use mathematics to kill boring time. The more you spend time, the more brilliant you will be.

2. What kind of application is boring mathematics?

With a good vision, further planning is needed. In order to realize the original intention, this application must have the following characteristics:

  • Easy to use at your fingertips, no need to install: If you need to install such a lightweight application, it will be really unnecessary trouble for users;
  • Convenient entrance, display simple and key information at all times: Help users overcome brain laziness and open boring math before opening short videos;
  • The UI is simple to operate and eye-catching: After all, math problems require thinking, and users can think while looking;
  • Quick development, quick launch, quick iteration;
  • Mathematical questions focus on logical reasoning and do not pile up mathematical knowledge;

In view of the above characteristics, Boring Math is very suitable to be developed into a meta-service of Hongmeng system. In terms of technical architecture, it is very suitable to be built using Huawei’s cloud integration technology. For details, please refer to the description in Table 1.

Table 1
Features of “Boring Mathematics” Huawei technical solutions
1. Easy to use at your fingertips, no installation required

Meta-service (formerly known as atomized service) is a future-oriented service provision method provided by HarmonyOS. It is a new application form that has an independent entrance, requires no installation, and can provide users with one or more convenient services.

For details, please refer to the official documentation.

2. Convenient entrance, simple and key information displayed at all times

The meta-service card allows users to obtain the display and dynamic changes of important information in the service without opening the meta-service. It can dynamically display the user’s problem-solving points, problem-solving progress, daily questions and other information.

3. The UI is simple to operate and eye-catching

Meta-services are developed using ArkUI, and ArkTS is the preferred main application development language for HarmonyOS. ArkTS is based on the TypeScript (TS for short) language extension and is a superset of TS. You can quickly build UI interfaces and implement operation logic.

For details, please read the official documentation

4. Rapid development, rapid launch, rapid iteration

1. The development tool DevEco is a device-cloud integrated low-code development platform based on Serverless and ArkUI. You can build meta-services through drag-and-drop development and visual configuration;

2. Serverless services include services such as cloud functions, cloud databases, cloud storage, and API gateways, which can be used as the backend of applications without the need to build a service architecture by yourself.

3. Get started

DevEco Studio is based on the IntelliJ IDEA Community open source version. It is a one-stop integrated development environment (IDE) for Huawei terminals in all scenarios and multiple devices. It provides developers with E2E HarmonyOS applications such as project template creation, development, compilation, debugging, and release/ Service development. The “Boring Math” meta-service is developed using DevEco Studio 3.1 Release.

The front-end of the Boring Mathematics meta-service is developed using ArkTS, and the back-end uses Serverless services. Therefore, create a new project in DevEco Studio and select the “Empty Ability with CloudDev” template. The project created by this template includes the development of the meta-service front-end and the Serverless back-end. There are two parts of end development. The specific selection path for the new project is “Create Project–>Atomic Service–>Empty Ability with CloudDev”. For specific operations, please refer to the screenshots below.

(1) Select the “Empty Ability with CloudDev” template:

Screenshot 2023-09-28 11.35.53.png

(2) Fill in the properties of the project, where the Bundle name needs to be consistent with the package name of the meta-service application created in AppGallery Connect.

Screenshot 2023-09-28 11.50.21.png

(3) The new project is associated with the meta-service application created in AppGallery Connect, which is automatically completed by the IDE.

Screenshot 2023-09-28 11.40.18.png

After the project is created, you can see that it is mainly composed of two parts. One part is Application, which is used to develop the front-end of meta-services, and the other part is CloudProgram, which is used to develop serverless services. In the subsequent chapters, introduction and design development will be carried out.

Screenshot 2023-09-28 12.15.57.png

4. Client design and development

  1. App’s theme color

    Considering that the interface is eye-catching and durable, dark blue is used as the main color. In order to avoid being too single and boring, a more lively blue-green is used as the auxiliary color. In order to avoid dazzling the eyes, the text title uses a color with a certain grayscale. As shown below.

    Color definition.png

    The entire application needs to use these theme colors, so these theme colors can be defined as a public file color.json and global constants for repeated use. As shown below.

    Screenshot 2023-09-27 20.55.03.png

    color.json is a json file, as follows:

    {
      "color": [
        {
          "name": "main_blue",
          "value": "#143254"
        },
        {
          "name" : "light_blue",
          "value" : "#17426d"
        },
        {
          "name" : "lighter_blue",
          "value" : "#3e5d79"
        },
        {
          "name" : "theme_green",
          "value" : "#65a645"
        },
        {
          "name" : "main_text_color",
          "value" : "#c8c7c7"
        },
        {
          "name" : "title_color",
          "value" : "#5a5b5b"
        }
      ]
    }</code>Copy

  2. Design and development of service cards

    Let’s look at the renderings first. The design of the meta-service card needs to comply with Huawei’s official requirements. Under this premise, the color adopts the theme color of this application and is visually consistent.

    Card effect.png

    The cards are in a stacked layout as shown.

    Card picture.png

    The specific layout code is as follows:

     @Builder buildStaticPictureCard(){
        Stack() {
          Image($r("app.media.card_bg"))
            .width(this.FULL_WIDTH_PERCENT)
            .height(this.FULL_HEIGHT_PERCENT)
            .objectFit(ImageFit.Cover)
    
          Column() {
            Column(){
              Text('Boring Math')
                .fontSize('14fp')
                .textOverflow({ overflow: TextOverflow.Ellipsis })
                .fontColor('#C2C2C2')
                .maxLines(1)
    
              Text('Use mathematics to kill boring time')
                .fontSize('10fp')
                .textOverflow({ overflow: TextOverflow.Ellipsis })
                .fontColor('#C2C2C2')
                .maxLines(2)
                .margin({top:'6fp'})
            }
            .width('100%')
            .height('60fp')
            .backgroundColor('#17426d')
            .padding({top:'12fp',left : '10fp', right : '10fp'})
            .alignItems(HorizontalAlign.Start)
            .justifyContent(FlexAlign.Start)
    
          }
          .width('100%')
          .height('100%')
          .alignItems(HorizontalAlign.Center)
          .justifyContent(FlexAlign.Start)
    
        }
        .width(this.FULL_WIDTH_PERCENT)
        .height(this.FULL_HEIGHT_PERCENT)
        .backgroundColor($r('app.color.main_background'))
        .onClick(() => {
          postCardAction(this, {
            "action": this.ACTION_TYPE,
            "abilityName": this.ABILITY_NAME,
            "params": {
              "message": this.MESSAGE
            }
          });
        })
      }</code>Copy

  3. Main function page

One of the biggest features of meta-services is that it is a card-style service. Key information can be presented on the card. After the user clicks on the card, the content of the service should be immediately displayed. After the user clicks on the boring math card, he directly opens the main function page. The answers to mathematics are mainly numbers. Furthermore, calculators are daily necessities and are very familiar to users. They can recognize them at a glance. Therefore, the main function page is designed and developed according to the calculator. This page uses the SideBarContainer container. The layout is as shown below.

Home1.png

SideBarContainer is a sidebar container that can be displayed and hidden. The sidebar and content area are defined through subcomponents. The first subcomponent represents the sidebar, and the second subcomponent represents the content area.

The specific code for SideBarContainer layout is as follows:

 build() {
    SideBarContainer(SideBarContainerType.Overlay) {
      //The first subcomponent represents the sidebar
      this.PageSideBarContainer()
      //The second subcomponent represents the content area
      this.PageContent()
    }
    .controlButton({
      left: 10,
      top: 10,
      width: 28,
      height: 28,
      icons: {
        shown: $r('app.media.ic_more'),
        hidden: $r('app.media.ic_more'),
        switching: $r('app.media.ic_more_back')
      }
    })
    .showSideBar(this.isShowSideBar)
    .sideBarPosition(SideBarPosition.Start)
    .sideBarWidth('55%')
    .minSideBarWidth('50%')
    .maxSideBarWidth('60%')
    .autoHide(true)
  }
</code>Copy

Grid grid container is composed of cells divided by “rows” and “columns”. Various layouts can be made by specifying the cell where the “item” is located, and includes the sub-component GridItem.

Grid() {
        GridItem() {
          this.DigitalButton('1', ButtonType.Circle)
        }
        GridItem() {
          this.DigitalButton('2', ButtonType.Circle)
        }
        GridItem() {
          this.DigitalButton('3', ButtonType.Circle)
        }
        GridItem() {
          this.levelButton('Level')
        }
        GridItem() {
          this.clearInput('clear')
        }
        GridItem() {
          this.DigitalButton('4', ButtonType.Circle)
        }
        GridItem() {
          this.DigitalButton('5', ButtonType.Circle)
        }
        GridItem() {
          this.DigitalButton('6', ButtonType.Circle)
        }
        GridItem() {
          this.DigitalButton('.', ButtonType.Circle)
        }
        GridItem() {
          this.ConfirmButton('Confirm')
        }.rowStart(2)
        .rowEnd(3)
        
        GridItem() {
          this.DigitalButton('7', ButtonType.Circle)
        }
        GridItem() {
          this.DigitalButton('8', ButtonType.Circle)
        }

        GridItem() {
          this.DigitalButton('9', ButtonType.Circle)
        }
        GridItem() {
          this.DigitalButton('0', ButtonType.Circle)
        }
      }
      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
      .rowsTemplate('1fr 1fr 1fr')
      .rowsGap(8)
      .columnsGap(8)
      .width('100%')
      .height('100%')
      .margin({ top: 10 })
      .align(Alignment.Center)
      .border({ width: 0 })
      .layoutDirection(GridDirection.Row)</code>Copy

5. Cloud design and development

Meta-services and AppGallery Connect services are naturally integrated. Therefore, it should be the best choice to build the backend of meta-service applications using serverless. Serverless provides a wide range of services, including basic cloud functions, cloud databases, cloud storage and App gateway services. At the same time, the account system of Boring Math is developed based on the serverless authentication service. The serverless authentication service provides a wide range of account authentication methods, including common authentication methods, such as: mobile phone number, email address, Huawei account, WeChat, QQ, apple, etc.

Boring Math supports multi-end applications. The server uses the serverless service of AppGallery Connect. In addition to meta-services, the front-end also supports small programs, apps and quick applications, as shown in the figure.

Screenshot 2023-09-28 16.28.10.png

It is very convenient to use DevEco Studio to develop cloud services. You can easily develop cloud functions and create data models. The following examples illustrate.

Boring Math will calculate the user’s score for each question based on the user’s time and accuracy in solving the problem, and save the score to the cloud to prevent loss. In this small scene, the meta-service front-end records the time and accuracy of user problem solving, and calls cloud functions to process related logic. Finally, the score record is recorded using the data model QuestionScore and saved to the cloud database.

Screenshot 2023-09-28 15.53.38.png

5.1 Add data QuestionScore object

1695886725955.jpg

After creating a new data model, you will get a QuestionScore.json file. The information described in this file includes four parts: data model name objectTypeName, access permissions, indexes, and fields. After editing the data model, you can select “Deploy Cloud DB” to publish the model to the cloud database.

{
  "objectTypeName": "QuestionScore",
  "permissions": [
    ...
  ],
  "indexes": [
    {
      "indexName": "questionNo",
      "indexList": [
        {
          "fieldName": "questionNo",
          "sortType": "ASC"
        }
      ]
    },
    ...
  ],
  "fields": [
    {
      "isNeedEncrypt": false,
      "fieldName": "scoreId",
      "notNull": true,
      "isSensitive": false,
      "belongPrimaryKey": true,
      "fieldType": "String"
    },
    ...
  ]
}</code>Copy

After the data type is successfully published, you can see the QuestionScore type in the AppGallery Connect management background, as shown in the figure below.

Database screenshot.jpg

5.2 Develop cloud functions

(1) Create a new cloud function

Use DevEco Studio to develop a cloud function “add-question-score” to calculate user scores and process related logic, and finally save the results to the cloud database. The specific operation is shown in the figure below.

Cloud function.jpg

(2) Configure cloud functions

To access the cloud database by a cloud function, you need to do some configuration first, download the agconnect-services.json file from AppGallery Connect, and place it in the cloud function update directory.

peizhi.jpg

(3) Initialize agcClient in the cloud function:

const credentialPath = "agc-apiclient-xxxx.json";
const clientName = "clientCN";
const region = "CN";
const zoneName = 'appsDataZone';
var agcClient = null;
///
agconnect.AGCClient.initialize(agconnect.CredentialParser.toCredential(path.join(__dirname, credentialPath)), clientName, region);
agcClient = agconnect.AGCClient.getInstance(clientName);</code>Copy

(4) Perform database access:

const clouddb = require('@hw-agconnect/database-server/dist/index.js');

clouddb.AGConnectCloudDB.initialize(agcClient);
const cloudDBZoneConfig = new clouddb.CloudDBZoneConfig(zoneName);
const cloudDBZoneClient = clouddb.AGConnectCloudDB.getInstance(agcClient).openCloudDBZone(cloudDBZoneConfig);
/
//2.Insert into QuestionScore
const scoreId = crypto.randomUUID().replace(/-/g, "");
const questionScore = clouddb.CloudDBZoneGenericObject.build('QuestionScore');
questionScore.addFieldValue('scoreId', scoreId, true);
questionScore.addFieldValue('questionNo', Number(curQuesNo));
questionScore.addFieldValue('userId', userId);
questionScore.addFieldValue('score', Number(score));
questionScore.addFieldValue('timeSeconds', Number(timeSeconds));
questionScore.addFieldValue('answerTimes', Number(answerTimes));
questionScore.addFieldValue('createdTime', new Date());
questionScore.addFieldValue('updatedTime', new Date());
//
const respQuestionScoreNum = await cloudDBZoneClient.executeUpsert(questionScore);
logger.info("QuestionScore->currentQuestionNo-> respQuestionScoreNum: " + respQuestionScoreNum);</code>Copy

(5) Publish cloud functions

After writing the cloud function, you can publish the cloud function. As shown before, right-click the “add-question-score” function and click “Deploy Function”. If everything goes well, you can publish the cloud function.

After successful publishing, you can see the cloud function in AppGallery Connect, as shown in the figure below.

fun function.jpg

6. Summary

This article introduces the conception process of Boring Mathematics and the development process of the technical solution using Huawei’s cloud integration, including the development process of meta-service cards and cloud. The entire development process involves many details and the space is limited. It is impossible to introduce them one by one in this article. I hope this article can inspire readers.

Finally, the meta-service and WeChat applet of “Boring Mathematics” have been launched. Readers are welcome to use Boring Mathematics and perform mental gymnastics.

Click to enter the Huawei zone to unlock more exciting content