|
@@ -0,0 +1,420 @@
|
|
|
|
+#include <SDL_error.h>
|
|
|
|
+#include <SDL_events.h>
|
|
|
|
+#include <SDL_mutex.h>
|
|
|
|
+#include <SDL_render.h>
|
|
|
|
+#include <SDL_stdinc.h>
|
|
|
|
+#include <SDL_video.h>
|
|
|
|
+#include <string.h>
|
|
|
|
+#include "ui.h"
|
|
|
|
+
|
|
|
|
+#define MAX_PATH_NUM 1024
|
|
|
|
+
|
|
|
|
+const char *resources = "/home/stone/Project/netscore/";
|
|
|
|
+
|
|
|
|
+// 绘制数字
|
|
|
|
+static void drawBigNumber(SDL_Renderer* renderer, SDL_Texture* numberTexture, int x, int y) {
|
|
|
|
+ static const int NumberWidth = 344, NumberHeight = 573;
|
|
|
|
+ SDL_Rect dstRect = {x, y, NumberWidth, NumberHeight};
|
|
|
|
+ SDL_RenderCopy(renderer, numberTexture, NULL, &dstRect);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 绘制数字
|
|
|
|
+static void drawSmallNumber(SDL_Renderer* renderer, SDL_Texture* numberTexture, int x, int y) {
|
|
|
|
+ static const int NumberWidth = 290, NumberHeight = 484;
|
|
|
|
+ SDL_Rect dstRect = {x, y, NumberWidth, NumberHeight};
|
|
|
|
+ SDL_RenderCopy(renderer, numberTexture, NULL, &dstRect);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void drawBox(SDL_Renderer* renderer, SDL_Texture* boxTexture, int x, int y) {
|
|
|
|
+ static const int NumberWidth = 892, NumberHeight = 1044;
|
|
|
|
+ SDL_Rect dstRect = {x, y, NumberWidth, NumberHeight};
|
|
|
|
+ SDL_RenderCopy(renderer, boxTexture, NULL, &dstRect);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void drawWin(SDL_Renderer* renderer, SDL_Texture* winTexture, int x, int y) {
|
|
|
|
+ static const int NumberWidth = 639, NumberHeight = 193;
|
|
|
|
+ SDL_Rect dstRect = {x, y, NumberWidth, NumberHeight};
|
|
|
|
+ SDL_RenderCopy(renderer, winTexture, NULL, &dstRect);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void drawNameTexture(struct Application *app, SDL_Texture *texture, int x, int y) {
|
|
|
|
+ static const int NameWidth = 1120, NameHeight = 118;
|
|
|
|
+
|
|
|
|
+ // 获取纹理的宽度和高度
|
|
|
|
+ int textureWidth, textureHeight;
|
|
|
|
+ SDL_QueryTexture(texture, NULL, NULL, &textureWidth, &textureHeight);
|
|
|
|
+
|
|
|
|
+ // 计算居中显示时的位置
|
|
|
|
+ int centerX = x + (NameWidth - textureWidth) / 2;
|
|
|
|
+ int centerY = y + (NameHeight - textureHeight) / 2;
|
|
|
|
+
|
|
|
|
+ // 创建目标矩形
|
|
|
|
+ SDL_Rect dstRect = { centerX, centerY, textureWidth, textureHeight };
|
|
|
|
+
|
|
|
|
+ SDL_RenderCopy(app->renderer, texture, NULL, &dstRect);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static SDL_Texture* loadTexture(struct Application *app, const char *path) {
|
|
|
|
+ SDL_Surface* surface = IMG_Load(path);
|
|
|
|
+ if (!surface) {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SDL_Texture* texture = SDL_CreateTextureFromSurface(app->renderer, surface);
|
|
|
|
+ SDL_FreeSurface(surface);
|
|
|
|
+ return texture;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int initApplication(struct Application *app) {
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ app->ret = 0;
|
|
|
|
+ app->errorString[0] = '\0';
|
|
|
|
+
|
|
|
|
+ app->initialized = 0;
|
|
|
|
+
|
|
|
|
+ app->window = NULL;
|
|
|
|
+ app->winWidth = 0;
|
|
|
|
+ app->winHeight = 0;
|
|
|
|
+
|
|
|
|
+ app->renderer = NULL;
|
|
|
|
+
|
|
|
|
+ app->bgTexture = NULL;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 10; i++)
|
|
|
|
+ app->bigNumTextures[i] = NULL;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 10; i++)
|
|
|
|
+ app->smallNumTextures[i] = NULL;
|
|
|
|
+
|
|
|
|
+ app->nameFont = NULL;
|
|
|
|
+
|
|
|
|
+ app->p1NameTexture = app->p2NameTexture = NULL;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 2; i++)
|
|
|
|
+ app->p1WinTexture[i] = app->p2WinTexture[i] = NULL;
|
|
|
|
+
|
|
|
|
+ app->scoreHighLightTexture[0] = app->scoreHighLightTexture[1] = NULL;
|
|
|
|
+
|
|
|
|
+ app->p1Name[0] = '\0';
|
|
|
|
+ app->p2Name[0] = '\0';
|
|
|
|
+ app->roundNum = app->roundNumSt = app->roundNumNd = 0;
|
|
|
|
+ app->p1Num = app->p1NumSt = app->p1NumNd = 0;
|
|
|
|
+ app->p2Num = app->p2NumSt = app->p2NumNd = 0;
|
|
|
|
+ app->p1Win = app->p2Win = 0;
|
|
|
|
+ app->isKey = 0;
|
|
|
|
+
|
|
|
|
+ app->updateRequire = 1;
|
|
|
|
+ app->mutex = NULL;
|
|
|
|
+
|
|
|
|
+ if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: SDL_Init: %s", SDL_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ app->initialized = 1;
|
|
|
|
+
|
|
|
|
+ if (TTF_Init() == -1) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: TTF_Init: %s", TTF_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ app->window = SDL_CreateWindow("计分板", 0, 0, 3840, 1100, SDL_WINDOW_FULLSCREEN);
|
|
|
|
+ if (!app->window) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: SDL_CreateWindow: %s", SDL_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SDL_GetWindowSize(app->window, &app->winWidth, &app->winHeight);
|
|
|
|
+
|
|
|
|
+ app->renderer = SDL_CreateRenderer(app->window, -1, SDL_RENDERER_ACCELERATED);
|
|
|
|
+ if (!app->renderer) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: SDL_CreateRenderer: %s", SDL_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 加载背景图片
|
|
|
|
+ {
|
|
|
|
+ char path[MAX_PATH_NUM];
|
|
|
|
+ snprintf(path, MAX_PATH_NUM, "%s%s%s", resources, "img/", "bg.png");
|
|
|
|
+
|
|
|
|
+ SDL_Surface* surface = IMG_Load(path);
|
|
|
|
+ if (!surface) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load bg image %s: %s", path, IMG_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ app->bgTexture = SDL_CreateTextureFromSurface(app->renderer, surface);
|
|
|
|
+ SDL_FreeSurface(surface);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 10; i++) {
|
|
|
|
+ char path[MAX_PATH_NUM];
|
|
|
|
+ snprintf(path, MAX_PATH_NUM, "%s%s/%d.png", resources, "img/big", i);
|
|
|
|
+
|
|
|
|
+ app->bigNumTextures[i] = loadTexture(app, path);
|
|
|
|
+ if (!app->bigNumTextures[i]) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load big numer image %s: %s", path, IMG_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 10; i++) {
|
|
|
|
+ char path[MAX_PATH_NUM];
|
|
|
|
+ snprintf(path, MAX_PATH_NUM, "%s%s/%d.png", resources, "img/small", i);
|
|
|
|
+
|
|
|
|
+ app->smallNumTextures[i] = loadTexture(app, path);
|
|
|
|
+ if (!app->smallNumTextures[i]) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load small numer image %s: %s", path, IMG_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ char path[MAX_PATH_NUM];
|
|
|
|
+ snprintf(path, sizeof(path), "%s%s%s", resources, "font/", "msyh.ttc");
|
|
|
|
+ app->nameFont = TTF_OpenFont(path, 120);
|
|
|
|
+ if (app->nameFont == NULL) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load font path %s: %s", path, TTF_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 2; ++i) {
|
|
|
|
+ char path[MAX_PATH_NUM];
|
|
|
|
+ snprintf(path, sizeof(path), "%s%s%s_%d.png", resources, "img/", "box", i);
|
|
|
|
+
|
|
|
|
+ app->scoreHighLightTexture[i] = loadTexture(app, path);
|
|
|
|
+ if (!app->scoreHighLightTexture[i]) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load box image %s: %s", path, IMG_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 2; ++i) {
|
|
|
|
+ char path[MAX_PATH_NUM];
|
|
|
|
+
|
|
|
|
+ snprintf(path, sizeof(path), "%s%s%s_%d.png", resources, "img/", "p1_win", i);
|
|
|
|
+ app->p1WinTexture[i] = loadTexture(app, path);
|
|
|
|
+ if (!app->p1WinTexture[i]) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load p1_win image %s: %s", path, IMG_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ snprintf(path, sizeof(path), "%s%s%s_%d.png", resources, "img/", "p2_win", i);
|
|
|
|
+ app->p2WinTexture[i] = loadTexture(app, path);
|
|
|
|
+ if (!app->p2WinTexture[i]) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load p2_win image %s: %s", path, IMG_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ app->mutex = SDL_CreateMutex();
|
|
|
|
+ if (app->mutex == NULL) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create mutex error: %s", SDL_GetError());
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void drawApplication(struct Application *app) {
|
|
|
|
+ // 清空渲染器
|
|
|
|
+ SDL_RenderClear(app->renderer);
|
|
|
|
+
|
|
|
|
+ SDL_Color textColor = { 255, 255, 255 }; // 白色
|
|
|
|
+
|
|
|
|
+ SDL_Surface* surface = NULL;
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ SDL_Surface* surface = NULL;
|
|
|
|
+
|
|
|
|
+ if (strnlen(app->p1Name, sizeof(app->p1Name)) != 0) {
|
|
|
|
+ surface = TTF_RenderUTF8_Solid(app->nameFont, app->p1Name, textColor);
|
|
|
|
+ if (!surface) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create utf-8 surface error %s: %s", app->p1Name, TTF_GetError());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (app->p1NameTexture)
|
|
|
|
+ SDL_DestroyTexture(app->p1NameTexture);
|
|
|
|
+ app->p1NameTexture = NULL;
|
|
|
|
+
|
|
|
|
+ if (surface) {
|
|
|
|
+ app->p1NameTexture = SDL_CreateTextureFromSurface(app->renderer, surface);
|
|
|
|
+ if (!app->p1NameTexture) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create texture error %s", SDL_GetError());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SDL_FreeSurface(surface);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ {
|
|
|
|
+ if (strnlen(app->p2Name, sizeof(app->p2Name)) != 0) {
|
|
|
|
+ surface = TTF_RenderUTF8_Solid(app->nameFont, app->p2Name, textColor);
|
|
|
|
+ if (!surface) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create utf-8 surface error %s: %s", app->p2Name, TTF_GetError());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (app->p2NameTexture)
|
|
|
|
+ SDL_DestroyTexture(app->p2NameTexture);
|
|
|
|
+ app->p2NameTexture = NULL;
|
|
|
|
+
|
|
|
|
+ if (surface) {
|
|
|
|
+ app->p2NameTexture = SDL_CreateTextureFromSurface(app->renderer, surface);
|
|
|
|
+ if (!app->p2NameTexture) {
|
|
|
|
+ snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create texture error %s", SDL_GetError());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SDL_FreeSurface(surface);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 绘制背景图片
|
|
|
|
+ SDL_RenderCopy(app->renderer, app->bgTexture, NULL, NULL);
|
|
|
|
+
|
|
|
|
+ drawBox(app->renderer, app->scoreHighLightTexture[app->isKey], 1475, 29);
|
|
|
|
+
|
|
|
|
+ if (app->p1NameTexture)
|
|
|
|
+ drawNameTexture(app, app->p1NameTexture, 233, 136);
|
|
|
|
+ if (app->p2NameTexture)
|
|
|
|
+ drawNameTexture(app, app->p2NameTexture, 2490, 136);
|
|
|
|
+
|
|
|
|
+ drawSmallNumber(app->renderer, app->smallNumTextures[app->roundNumSt], 1589, 409);
|
|
|
|
+ drawSmallNumber(app->renderer, app->smallNumTextures[app->roundNumNd], 1962, 409);
|
|
|
|
+
|
|
|
|
+ drawBigNumber(app->renderer, app->bigNumTextures[app->p1NumSt], 455, 317);
|
|
|
|
+ drawBigNumber(app->renderer, app->bigNumTextures[app->p1NumNd], 896, 317);
|
|
|
|
+
|
|
|
|
+ drawBigNumber(app->renderer, app->bigNumTextures[app->p2NumSt], 2600, 317);
|
|
|
|
+ drawBigNumber(app->renderer, app->bigNumTextures[app->p2NumNd], 3041, 317);
|
|
|
|
+
|
|
|
|
+ drawWin(app->renderer, app->p1WinTexture[app->p1Win], 528, 883);
|
|
|
|
+ drawWin(app->renderer, app->p2WinTexture[app->p2Win], 2673, 883);
|
|
|
|
+
|
|
|
|
+ SDL_RenderPresent(app->renderer);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void termApplication(struct Application *app) {
|
|
|
|
+ if (app->initialized == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (app->mutex)
|
|
|
|
+ SDL_DestroyMutex(app->mutex);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 2; i++)
|
|
|
|
+ if (app->scoreHighLightTexture[i])
|
|
|
|
+ SDL_DestroyTexture(app->scoreHighLightTexture[i]);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 2; i++) {
|
|
|
|
+ if (app->p1WinTexture[i])
|
|
|
|
+ SDL_DestroyTexture(app->p1WinTexture[i]);
|
|
|
|
+ if (app->p2WinTexture[i])
|
|
|
|
+ SDL_DestroyTexture(app->p2WinTexture[i]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (app->p1NameTexture)
|
|
|
|
+ SDL_DestroyTexture(app->p1NameTexture);
|
|
|
|
+
|
|
|
|
+ if (app->p2NameTexture)
|
|
|
|
+ SDL_DestroyTexture(app->p2NameTexture);
|
|
|
|
+
|
|
|
|
+ if (app->nameFont)
|
|
|
|
+ TTF_CloseFont(app->nameFont);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 10; i++)
|
|
|
|
+ if (app->smallNumTextures[i])
|
|
|
|
+ SDL_DestroyTexture(app->smallNumTextures[i]);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 10; i++)
|
|
|
|
+ if (app->bigNumTextures[i])
|
|
|
|
+ SDL_DestroyTexture(app->bigNumTextures[i]);
|
|
|
|
+
|
|
|
|
+ if (app->bgTexture)
|
|
|
|
+ SDL_DestroyTexture(app->bgTexture);
|
|
|
|
+
|
|
|
|
+ if (app->renderer)
|
|
|
|
+ SDL_DestroyRenderer(app->renderer);
|
|
|
|
+
|
|
|
|
+ if (app->window)
|
|
|
|
+ SDL_DestroyWindow(app->window);
|
|
|
|
+
|
|
|
|
+ if (TTF_WasInit())
|
|
|
|
+ TTF_Quit();
|
|
|
|
+
|
|
|
|
+ SDL_Quit();
|
|
|
|
+ app->initialized = 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int updateApplicationMode(struct Application *app, uint8 isKey) {
|
|
|
|
+ app->isKey = isKey;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int updateApplication(struct Application *app, const char *p1Name, const char *p2Name, int roundNum, int p1Score, int p2Score) {
|
|
|
|
+ printf("%s, %s, %d, %d, %d\n", p1Name, p2Name, roundNum, p1Score, p2Score);
|
|
|
|
+ SDL_LockMutex(app->mutex);
|
|
|
|
+
|
|
|
|
+ if ((strcmp(p1Name, app->p1Name) == 0 && strcmp(p2Name, app->p2Name) == 0) ||
|
|
|
|
+ (strcmp(p1Name, app->p2Name) == 0 && strcmp(p2Name, app->p1Name))) {
|
|
|
|
+ if (p1Score - app->p1Num == 1 && p2Score == app->p2Num) {
|
|
|
|
+ app->p1Win = 1;
|
|
|
|
+ } else {
|
|
|
|
+ app->p1Win = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (p1Score == app->p1Num && p2Score - app->p2Num == 1) {
|
|
|
|
+ app->p2Win = 1;
|
|
|
|
+ } else {
|
|
|
|
+ app->p2Win = 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (p1Name != app->p1Name && strcmp(p1Name, app->p1Name) != 0 && strlen(p1Name) <= 30) {
|
|
|
|
+ memset(app->p1Name, 0, sizeof(app->p1Name));
|
|
|
|
+ strncpy(app->p1Name, p1Name, sizeof(app->p1Name) - 1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (p2Name != app->p2Name && strcmp(p2Name, app->p2Name) != 0 && strlen(p2Name) <= 30) {
|
|
|
|
+ memset(app->p2Name, 0, sizeof(app->p2Name));
|
|
|
|
+ strncpy(app->p2Name, p2Name, sizeof(app->p2Name) - 1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ app->roundNum = roundNum % 100;
|
|
|
|
+ app->roundNumSt = (app->roundNum / 10) % 10;
|
|
|
|
+ app->roundNumNd = app->roundNum % 10;
|
|
|
|
+
|
|
|
|
+ app->p1Num = p1Score % 100;
|
|
|
|
+ app->p1NumSt = (app->p1Num / 10) % 10;
|
|
|
|
+ app->p1NumNd = app->p1Num % 10;
|
|
|
|
+
|
|
|
|
+ app->p2Num = p2Score % 100;
|
|
|
|
+ app->p2NumSt = (app->p2Num / 10) % 10;
|
|
|
|
+ app->p2NumNd = app->p2Num % 10;
|
|
|
|
+
|
|
|
|
+ SDL_UnlockMutex(app->mutex);
|
|
|
|
+
|
|
|
|
+ app->updateRequire = 1;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+int main() {
|
|
|
|
+ struct Application myApp, *app = &myApp;
|
|
|
|
+
|
|
|
|
+ if (initApplication(app)) {
|
|
|
|
+ printf("初始化应用失败: %s\n", app->errorString);
|
|
|
|
+ termApplication(app);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (app->initialized) {
|
|
|
|
+ updateApplication(app, "昵称最多有八个字", "昵称最多有八个字", 5, 6, 6);
|
|
|
|
+ runApplication(app);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ termApplication(app);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}*/
|