First_Commit

This commit is contained in:
2025-07-23 23:06:27 +08:00
commit d35d096374
27 changed files with 2528 additions and 0 deletions

6
.clang-format Normal file
View File

@@ -0,0 +1,6 @@
BasedOnStyle: LLVM
IndentWidth: 4
AccessModifierOffset: -4
AllowShortFunctionsOnASingleLine: Inline
AlwaysBreakTemplateDeclarations: Yes
PackConstructorInitializers: Never

492
.gitignore vendored Normal file
View File

@@ -0,0 +1,492 @@
# .gitignore file for CLion, Visual Studio, and Visual Studio Code
# From JetBrains .gitignore template
# https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# From Visual Studio .gitignore template
# https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
# .vscode/*
# !.vscode/settings.json
# !.vscode/tasks.json
# !.vscode/launch.json
# !.vscode/extensions.json
# *.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains
*.sln.iml
/.idea/
# Custom writen VSCode .gitignore
.vscode/
# Default build directory for CMake extension
build/
*_build/

100
CMakeLists.txt Normal file
View File

@@ -0,0 +1,100 @@
# ! ------------------------------------------------------------------ !
# ! Changing this file incorrectly can cause your program to not build !
# ! If you don't know CMake well DO NOT touch this file !
# ! ------------------------------------------------------------------ !
cmake_minimum_required(VERSION 3.20)
project(OOP VERSION 0.1.0)
enable_testing()
set(CMAKE_CXX_STANDARD 17)
#### GTest
option(FETCH_GOOGLETEST "Download googletest source" ON)
if(FETCH_GOOGLETEST)
# reference: https://google.github.io/googletest/quickstart-cmake.html
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
else()
message("Using custom googletest installation")
# reference: https://cmake.org/cmake/help/latest/module/FindGTest.html
find_package(GTest REQUIRED)
endif()
include(files.cmake)
set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include)
set(TEST_DIR ${CMAKE_SOURCE_DIR}/test)
list(TRANSFORM SRC_FILES PREPEND ${SRC_DIR}/)
list(TRANSFORM INCLUDE_FILES PREPEND ${INCLUDE_DIR}/)
list(TRANSFORM TEST_FILES PREPEND ${TEST_DIR}/)
find_program(MEMORYCHECK_COMMAND valgrind)
set(MEMORYCHECK_COMMAND_OPTIONS
"--error-exitcode=1 --track-origins=yes --leak-check=full"
)
include(CTest)
option(COVERAGE "Enable coverage" OFF)
if(COVERAGE)
set(CMAKE_C_FLAGS "--coverage -g -O0")
set(CMAKE_CXX_FLAGS "--coverage -g -O0")
include(scripts/CodeCoverage.cmake)
set(CODE_COVERAGE_VERBOSE ON)
set(COVERAGE_EXCLUDE
${CMAKE_BINARY_DIR}/_deps/*
${PROJECT_SOURCE_DIR}/test/*
)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(GCOVR_ADDITIONAL_ARGS
--gcov-executable "llvm-cov gcov"
)
endif()
append_coverage_compiler_flags()
setup_target_for_coverage_gcovr_html(
NAME ut_all_coverage
DEPENDENCIES ut_all
EXCLUDE ${COVERAGE_EXCLUDE}
)
endif()
if(MSVC)
set(TARGET_COMPILER_OPTIONS
/W4
)
else()
set(TARGET_COMPILER_OPTIONS
-Wall -pedantic
)
endif()
add_executable(ut_all
${SRC_FILES}
${INCLUDE_FILES}
${TEST_FILES}
)
target_link_libraries(ut_all
GTest::gtest_main
)
target_include_directories(ut_all PRIVATE
${INCLUDE_DIR}
)
target_compile_options(ut_all PRIVATE
${TARGET_COMPILER_OPTIONS}
)
include(GoogleTest)
gtest_discover_tests(ut_all)

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 NOOBDY
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

240
README.md Normal file
View File

@@ -0,0 +1,240 @@
# Homework 03
> 這份作業由物件導向程式設計助教群所製。
> 如有問題,歡迎使用以下方式聯繫助教:
>> Email: t111590004@ntut.org.tw
>> MS Teams: 張意昌
⚠️ Due: 2024/11/13 11:59 p.m. ⚠️
## 說明
### 目標
- [ ] 學會繼承以及其使用。
- [ ] 學會純虛擬函數。
- [ ] 學會 `std::share_ptr` 的應用。
### 檔案架構
請確認提交是否符合以下的檔案架構,否則無法進行評分。
```txt=
./
├── CMakeLists.txt
├── LICENSE
├── README.md
├── .gitignore
├── .clang-format
├── files.cmake
├── include
│ └── Drink.hpp
│ └── Food.hpp
│ └── Ingredients.hpp
│ └── MainDish.hpp
│ └── OishiiPapa.hpp
│ └── Order.hpp
│ └── Package.hpp
│ └── SideDish.hpp
├── scripts
│ ├── CodeCoverage.cmake
│ └── coverage.sh
├── src
│ └── Drink.cpp
│ └── Food.cpp
│ └── MainDish.cpp
│ └── OishiiPapa.cpp
│ └── Order.cpp
│ └── Package.cpp
│ └── SideDish.cpp
└── test
└── ut_Food.cpp
└── ut_Oishiipapa.cpp
└── ut_Package.cpp
```
## 題目評分
- 80%]完成第一部分。
- `MAINDISH_TEST` 20%
- `SIDEDISH_TEST` 20%
- `DRINK_TEST` 10%
- `PACKAGE_TEST` 30%
- 20%]完成第二部分。
- `OISHIIPAPA_TEST` 20%
- 依照完成部分比例給分,取上傳紀錄中最高者記錄之。
## 注意事項
- 你不應該上傳 `/bin` 資料夾至專案上。
- 你的功課不應該出現 Memory Leak否則將會扣作業總分 10 分。
- 你不應該上傳 `/bin` 資料夾至專案庫,編譯結果不應該上傳至專案庫上,若在助教確認功課評分時 `/bin` 資料夾存在在專案庫中,扣除作業總分 5 分。
## 敘述
> 嗨,歡迎參加 OOP 課程。
>
> 想必你已經完成了 Lecture 03 的課程,並瞭解有關於繼承的觀念。
> (若還不了解的話,可以查看 Lecture 03 的簡報)
>
> 在這個任務中,你會了解如何使用課堂上所描述的繼承觀念。
請嘗試完成任務,並在 Jenkins 上拿到綠色的 Correct 勾勾。
## 題目敘述
> 在這份任務中,我們嘗試設計出速食店的餐點。
`Original Oishii Papa` 是一間在世界各地有許多分店的美味速食店,`kesshoban` 想要在北科的藍光園地內開設一間分店,現在請你幫他完成一個簡單的管理系統。
由於 `Original Oishii Papa` 的核心精神是以簡單、美味為主,所以店內只有簡單的漢堡與美食組合,以下是他的餐點:
| 品名 |英文品名| 食材 | 價格 |
| -------- |-----| -------- | -------- |
| 豬肉堡 |PorkBurger| 一份豬排、一份生菜、一份漢堡麵包、一份起司 | 59 |
| 牛肉堡 |BeefBurger| 一份牛排、一份生菜、一份漢堡麵包、一份起司 | 69 |
| 魚排堡 |FishBurger| 一份魚排、一份生菜、一份漢堡麵包、一份起司 | 79 |
* 以上主餐會存在 `Ingredients.hpp` 的 `enum class Production` 裡。
當然,主餐也可以增加一些不同的配料,以下是可以增加的配料
| 品名 |英文品名| 價格 |
| -------- |-----| -------- |
| 豬肉 |PorkSteak| 20 |
| 牛肉 |BeefSteak| 20 |
| 魚排 |FishSteak| 20 |
| 生菜 |Lattuce | 10 |
| 起司 |Cheese | 10 |
* 以上主餐會存在 `Ingredients.hpp` 的 `enum class Ingredients` 裡,請參考食材名稱區。
| 品名 |英文品名| 食材 | 備註 |
| -------- |-----| -------- | -------- |
| 薯條 |Frenchfries| 一份薯條 | 小份44 <br> 大份59 |
| 雞塊 |Nugget| 一份雞塊 | 小份44 <br> 大份59 |
| 沙拉 |Salad| 一份沙拉 | 59 |
* 以上附餐會存在 `Ingredients.hpp` 的 `enum class Production` 裡。
| 品名 |英文品名| 食材 | 備註 |
| -------- |-----| -------- | -------- |
| 可樂 |Cola| 一份可樂 | 中杯28 <br> 大杯38 |
| 雪碧 |Spirit|一份雪碧 | 中杯28 <br> 大杯38 |
| 焦糖奶茶 |CaramelMilktea|一份奶茶、一份焦糖 | 中杯44 |
| 咖啡拿鐵 |Latte |一份咖啡、一份牛奶 | 中杯45 <br> 大杯55 |
* 以上飲料會存在 `Ingredients.hpp` 的 `enum class Production` 裡。
以上是整間速食店的餐點,接下來會給予相對應的食材。
| 食材中文 | 食材英文 |
| -------- | -------- |
| 豬排 | PorkSteak |
| 牛排 | BeefSteak |
| 魚排 | FishSteak |
| 漢堡麵包 | BurgerBread |
| 生菜 | Lattuce |
| 起司 | Cheese |
| 薯條 | FranchFries |
| 雞塊 | ChickenNugget |
| 沙拉 | Salad |
| 可樂 | Cola |
| 雪碧 | Spirit |
| 奶茶 | Milktea |
| 焦糖 | Caramel |
| 咖啡 | Coffee |
| 牛奶 | Milk |
* 以上食材會存在 `Ingredients.hpp` 的 `enum class Ingredients` 裡。
* 在 `Ingreditents.hpp` 內,所有的東西都會用英文呈現,例如:豬排堡是 `Production::PorkBurger` 。
### 任務一、在基礎類別中完成getter與setter
- 在本次任務中,有一個基礎類別,也就是 `Food.hpp`。
- 請於 `Food(Production id)` 內完成建構子。
- 請於 `void getid()` 這個 `function` 內,回傳 `Production id` 這個物件。
- 請於 `std::vector<Ingredients> GetIngredient()` 這個 `function` 內,回傳 `std::vector<Ingredients> ingredient` 這個物件。
- 請設置 `void MakeFood()` 為一個純虛擬函數。
- 請於 `int GetMoney()` 內 ,回傳 `int money` 這個物件。
### 任務二、在衍伸類別中完成物件
- 接下來會有三個 `class`,分別為 `maindish.hpp` 、 `sidedish.hpp` 、 `drink.hpp` ,這三個物件皆為 `food.hpp` 的衍伸物件,請根據對應的任務完成相對應的內容。
- 共通部分
- 對於 `void MakeFood()` 這個 `function` ,請覆寫掉 `food.hpp` 內的 `void CountMoney()` 這個 `function` ,請將對應的 `Production` 設置好特定的 `ingredients` 並塞入 `std::vector<Ingredients> ingredients` 內,並且計算好價格後放入 `money` 內。
- `maindish.hpp`
- 對於 `void AddIngredients(std::vector<Ingredients> addtional)` 加入 `std::vector<Ingredients> addtional` ,並且重新計算價格。
- 若 `addtional` 內有任一一項食材未出現在 `額外配料Addtional` 的表格內,請拋出 `std::invalid_argument` 。
- `sidedish.hpp`
- 除了 `沙拉` 以外的物件,如果 `void MakeLarger()` 被呼叫,你就要將 `SideDishType type` 設定成 `SideDishType::BIG` 。
- 對於 `SideDishType GetType()` ,你應該回傳 `SideDishType type` 。
- `drink.hpp`
- 除了 `焦糖奶茶` 以外的物件,如果 `void makelarger()` 被呼叫,你要將 `ml` 設定成 `750` 。
- 有以下一個部分請你要注意
- 在設計 `void MakeFood()` 時,請依照表格給的順序做填充,例如:豬排堡,那麼順序就是 `豬肉排、生菜、漢堡麵包、起司` 。
### 任務三、完成包裝的物件
- 接下來有一個叫做 `Package.hpp` 的檔案,是製作一份完整的餐點。
- 對於 `void SetMainDish(MainDish maindish)` 你應該要將 `maindish` 設置在 `std::shared_ptr<MainDish> maindish` 內。
- 對於 `void SetSideDish(SideDish sidedish)` 你應該要將 `sidedish` 設置在 `std::shared_ptr<SideDish> sidedish` 內。
- 對於 `void SetDrink(Drink drink)` 你應該要將 `drink` 設置在 `std::shared_ptr<Drink> drink` 內。
- 對於 `void CountMoney()` 你應該要計算當前這份 `Package` 內的餐點總價是多少後設定在 `money` 裡面,計算規則可以參考表格,並且當 `maindish` 、 `sidedish` 及 `drink` 都有東西時,請將 `money` 減少 `15`。
## 題目敘述 (Part 2)
接下來這個部分將會實作一個簡易的速食店系統,請根據對應的任務完成相對應的功能。
速食店的 `class` 為 `OishiiPapa.hpp` 。
### 任務一、觀察訂單物件
- 接下來請觀察 `Order.hpp` 這個物件,將會告訴你訂單的應用。
- `std::vector<Production> product` 內存放該筆訂單所需求的產品,我們保證順序一定是 `{主餐,附餐,飲料}` 。
- Ex: `std::vector<Production> product = {PorkBurger,_NULL,Cola}` 代表只需要 `豬排堡` 以及 `可樂` 。
- `std::vector<Ingredients> addtional` 內代表 `主餐` 所需要的加料。
- `std::vector<bool> larger` 代表 `附餐` 及 `飲料` 是否需要加大,我們保證順序一定是 `{附餐,飲料}` 。
- Ex: `std::vector<bool> larger = {false,true}` ,代表附餐不用加大但飲料一定要。
- 保證沒有出現的餐點的那欄一定是 `false` 。
- 根據 `std::vector<Production> GetProductInfo()` ,你應該回傳 `std::vector<Production> product` 。
- 根據 `std::vector<Ingredients> GetAddtionalInfo()` 你應該回傳 `std::vector<Ingredients> addtional` 。
- 根據 `std::vector<bool> GetLargerInfo` ,你應該回傳 `std::vector<bool> larger` 。
### 任務二、根據接收到的訂單製作物件
- 對於 `void SendOrder(Order order)` ,你應該將 `order` 傳入 `std::queue<Order> pipeline` 內。
- 對於 `void MakeDish()` ,請根據物件 `std::queue<Order> pipeline` 內最上方的 `Order` 回傳,進行相對應的 `Package` 製作,並且將製作好的物件放入 `std::queue<Package> chest` 內。
- 若當前的 `chest` 大小至少 `15` ,則不要製作餐點,將 `Order` 丟入 `std::queue<Order> pipeline` 內。
- 若當前的 `std::queue<Order> pipeline` 為空,則拋出 `std::out_of_range()` 。
### 任務三、進行餐點管理
- 對於 `Package Pickup()` 這個function請觀察 `std::queue<Package> chest` 這個物件,當 function 被呼叫時,你應該將最上面的 `Package` 回傳,並且對 `money` 進行調整,如果 `chest` 大小小於 `15` 且 `std::queue<Order> pipeline` 不為空,將 `std::queue<Order> pipeline` 內最上方的 `Order` 丟出來並製作餐點。
- 若當前的 `std::queue<Package> chest` 為空,則拋出 `std::out_of_range()` 。
### 任務提示
- 提示:你應該先取的 `chest` 最上方的 `Package` ,之後再判斷是否要製作新的餐點,然後回傳 `Package` 。
- `std::queue<Package> chest` 以及 `std::queue<Order> pipeline` 為 `queue` 這個資料結構,你應該去了解這個資料結構的用途,你可以參考[這篇](https://hackmd.io/@Ben1102/S1zcfIqnu)的介紹,用法會放在任務附註。
## 任務附註
- 你只需要實作任務所描述的function。
- 關於 `std::invalid_argument` ,你可以參考[這篇](https://en.cppreference.com/w/cpp/error/invalid_argument)。
- `std::invalid_argument`內可以寫任意東西。
- 關於 `std::out_of_range` ,你可以參考[這篇](https://en.cppreference.com/w/cpp/error/out_of_range)。
- `std::out_of_range`內可以寫任意東西。
- 關於 `std::queue` ,你可以參考[這篇](https://en.cppreference.com/w/cpp/container/queue)。
- 關於 `std::shared_ptr` ,你可以參考[這篇](https://en.cppreference.com/w/cpp/memory/shared_ptr)。
## Homework's meme
![meme](https://hackmd.io/_uploads/S1UnbyLbkg.png)

26
files.cmake Normal file
View File

@@ -0,0 +1,26 @@
set(SRC_FILES
Drink.cpp
Food.cpp
MainDish.cpp
OishiiPapa.cpp
Order.cpp
Package.cpp
SideDish.cpp
)
set(INCLUDE_FILES
Drink.hpp
Food.hpp
Ingredients.hpp
MainDish.hpp
OishiiPapa.hpp
Order.hpp
Package.hpp
SideDish.hpp
)
set(TEST_FILES
ut_Food.cpp
ut_Package.cpp
ut_Oishiipapa.cpp
)

22
include/Drink.hpp Normal file
View File

@@ -0,0 +1,22 @@
//
// Created by User on 2024/10/29.
//
#ifndef OOP_DRINK_HPP
#define OOP_DRINK_HPP
#include <stdexcept>
#include "Food.hpp"
#include "Ingredients.hpp"
class Drink final : public Food {
private:
int ml;
public:
Drink(Production id);
virtual void MakeFood() override;
void MakeLarger();
int GetMl();
};
#endif // OOP_DRINK_HPP

25
include/Food.hpp Normal file
View File

@@ -0,0 +1,25 @@
//
// Created by User on 2024/10/29.
//
#ifndef OOP_FOOD_HPP
#define OOP_FOOD_HPP
#include <string>
#include <vector>
#include "Ingredients.hpp"
class Food {
protected:
Production id;
std::vector<Ingredients> ingredient;
int money;
public:
Food(Production id);
Production getId() const;
std::vector<Ingredients> GetIngredient();
virtual void MakeFood() = 0;
int GetMoney();
};
#endif // OOP_FOOD_HPP

41
include/Ingredients.hpp Normal file
View File

@@ -0,0 +1,41 @@
//
// Created by User on 2024/10/29.
//
#ifndef OOP_INGREDIENTS_H
#define OOP_INGREDIENTS_H
enum class Ingredients: unsigned long long{
_NULL = 0,
PorkSteak,
BeefSteak,
FishSteak,
BurgerBread,
Lattuce,
Cheese,
FranchFries,
ChickenNugget,
Salad,
Cola,
Spirit,
Milktea,
Caramel,
Coffee,
Milk,
};
enum class Production: unsigned long long {
_NULL = 0,
PorkBurger,
BeefBurger,
FishBurger,
Frenchfries,
Nugget,
Salad,
Cola,
Spirit,
CaramelMilktea,
Latte,
};
#endif // OOP_INGREDIENTS_H

22
include/MainDish.hpp Normal file
View File

@@ -0,0 +1,22 @@
//
// Created by User on 2024/10/29.
//
#ifndef OOP_MAINDISH_HPP
#define OOP_MAINDISH_HPP
#include "Food.hpp"
#include <vector>
#include <stdexcept>
#include "Ingredients.hpp"
class MainDish : public Food {
private:
std::vector<Ingredients> addtional;
public:
MainDish(Production id);
void MakeFood() override;
void AddIngredients(std::vector<Ingredients> addtional);
};
#endif // OOP_MAINDISH_HPP

24
include/OishiiPapa.hpp Normal file
View File

@@ -0,0 +1,24 @@
#ifndef OISHII_PAPA_HPP
#define OISHII_PAPA_HPP
#include "Drink.hpp"
#include "MainDish.hpp"
#include "SideDish.hpp"
#include "Package.hpp"
#include "Order.hpp"
#include <queue>
class OishiiPapa{
private:
std::queue<Order> pipeline;
std::queue<Package> chest;
int money = 0;
public:
OishiiPapa();
void MakeDish();
void SendOrder(Order order);
Package Pickup();
int GetMoney();
Order GetOrderInfo();
};
#endif

19
include/Order.hpp Normal file
View File

@@ -0,0 +1,19 @@
#ifndef ORDER_HPP
#define ORDER_HPP
#include <vector>
#include "Ingredients.hpp"
class Order{
private:
std::vector<Production> product;
std::vector<Ingredients> addtional;
std::vector<bool> larger;
public:
Order(std::vector<Production> product, std::vector<Ingredients> addtional ,std::vector<bool> larger);
std::vector<Production> GetProductInfo();
std::vector<Ingredients> GetAddtionalInfo();
std::vector<bool> GetLargerInfo();
};
#endif

29
include/Package.hpp Normal file
View File

@@ -0,0 +1,29 @@
//
// Created by User on 2024/10/29.
//
#ifndef OOP_PACKAGE_HPP
#define OOP_PACKAGE_HPP
#include "MainDish.hpp"
#include "SideDish.hpp"
#include "Drink.hpp"
#include <stdexcept>
#include <memory>
class Package {
private:
std::shared_ptr<MainDish> maindish = nullptr;
std::shared_ptr<SideDish> sidedish = nullptr;
std::shared_ptr<Drink> drink = nullptr;
int money = 0;
public:
Package();
void CountMoney();
void SetMainDish(MainDish maindish);
void SetSideDish(SideDish sidedish);
void SetDrink(Drink drink);
int GetMoney();
};
#endif // OOP_PACKAGE_HPP

28
include/SideDish.hpp Normal file
View File

@@ -0,0 +1,28 @@
//
// Created by User on 2024/10/29.
//
#ifndef OOP_SIDEDISH_HPP
#define OOP_SIDEDISH_HPP
#include <string>
#include <stdexcept>
#include "Food.hpp"
#include "Ingredients.hpp"
enum class SideDishType {
BIG = 0,
SMALL = 1
};
class SideDish final : public Food {
private:
SideDishType type = SideDishType::SMALL;
public:
SideDish(Production id);
void MakeFood() override;
void MakeLarger();
SideDishType GetType();
};
#endif // OOP_SIDEDISH_HPP

26
score.json Normal file
View File

@@ -0,0 +1,26 @@
{
"homework_name": "HW3",
"semester": "2024f",
"testsuites": [
{
"testsuite": "MAINDISH_TEST",
"score": 20
},
{
"testsuite": "SIDEDISH_TEST",
"score": 20
},
{
"testsuite": "DRINK_TEST",
"score": 10
},
{
"testsuite": "PACKAGE_TEST",
"score": 30
},
{
"testsuite": "OISHIIPAPA_TEST",
"score": 20
}
]
}

742
scripts/CodeCoverage.cmake Normal file
View File

@@ -0,0 +1,742 @@
# Copyright (c) 2012 - 2017, Lars Bilke
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# CHANGES:
#
# 2012-01-31, Lars Bilke
# - Enable Code Coverage
#
# 2013-09-17, Joakim Söderberg
# - Added support for Clang.
# - Some additional usage instructions.
#
# 2016-02-03, Lars Bilke
# - Refactored functions to use named parameters
#
# 2017-06-02, Lars Bilke
# - Merged with modified version from github.com/ufz/ogs
#
# 2019-05-06, Anatolii Kurotych
# - Remove unnecessary --coverage flag
#
# 2019-12-13, FeRD (Frank Dana)
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
# - Set lcov basedir with -b argument
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
# - Delete output dir, .info file on 'make clean'
# - Remove Python detection, since version mismatches will break gcovr
# - Minor cleanup (lowercase function names, update examples...)
#
# 2019-12-19, FeRD (Frank Dana)
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
#
# 2020-01-19, Bob Apthorpe
# - Added gfortran support
#
# 2020-02-17, FeRD (Frank Dana)
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
# in EXCLUDEs, and remove manual escaping from gcovr targets
#
# 2021-01-19, Robin Mueller
# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
# flags to the gcovr command
#
# 2020-05-04, Mihchael Davis
# - Add -fprofile-abs-path to make gcno files contain absolute paths
# - Fix BASE_DIRECTORY not working when defined
# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
#
# 2021-05-10, Martin Stump
# - Check if the generator is multi-config before warning about non-Debug builds
#
# 2022-02-22, Marko Wehle
# - Change gcovr output from -o <filename> for --xml <filename> and --html <filename> output respectively.
# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt".
#
# 2022-09-28, Sebastian Mueller
# - fix append_coverage_compiler_flags_to_target to correctly add flags
# - replace "-fprofile-arcs -ftest-coverage" with "--coverage" (equivalent)
#
# USAGE:
#
# 1. Copy this file into your cmake modules path.
#
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
# using a CMake option() to enable it just optionally):
# include(CodeCoverage)
#
# 3. Append necessary compiler flags for all supported source files:
# append_coverage_compiler_flags()
# Or for specific target:
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
#
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
#
# 4. If you need to exclude additional directories from the report, specify them
# using full paths in the COVERAGE_EXCLUDES variable before calling
# setup_target_for_coverage_*().
# Example:
# set(COVERAGE_EXCLUDES
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
# '/path/to/my/src/dir2/*')
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
# Example:
# setup_target_for_coverage_lcov(
# NAME coverage
# EXECUTABLE testrunner
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
#
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
# Example:
# set(COVERAGE_EXCLUDES "dir1/*")
# setup_target_for_coverage_gcovr_html(
# NAME coverage
# EXECUTABLE testrunner
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
# EXCLUDE "dir2/*")
#
# 5. Use the functions described below to create a custom make target which
# runs your test executable and produces a code coverage report.
#
# 6. Build a Debug build:
# cmake -DCMAKE_BUILD_TYPE=Debug ..
# make
# make my_coverage_target
#
include(CMakeParseArguments)
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
# Check prereqs
find_program( GCOV_PATH gcov )
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
find_program( CPPFILT_PATH NAMES c++filt )
if(NOT GCOV_PATH)
message(FATAL_ERROR "gcov not found! Aborting...")
endif() # NOT GCOV_PATH
# Check supported compiler (Clang, GNU and Flang)
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(LANG ${LANGUAGES})
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif()
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif()
endforeach()
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
CACHE INTERNAL "")
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fprofile-abs-path HAVE_fprofile_abs_path)
if(HAVE_fprofile_abs_path)
set(COVERAGE_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif()
endif()
set(CMAKE_Fortran_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
FORCE )
set(CMAKE_CXX_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C++ compiler during coverage builds."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C compiler during coverage builds."
FORCE )
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used for linking binaries during coverage builds."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
FORCE )
mark_as_advanced(
CMAKE_Fortran_FLAGS_COVERAGE
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
link_libraries(gcov)
endif()
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_lcov(
# NAME testrunner_coverage # New target name
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES testrunner # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# NO_DEMANGLE # Don't demangle C++ symbols
# # even if c++filt is found
# )
function(setup_target_for_coverage_lcov)
set(options NO_DEMANGLE SONARQUBE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT LCOV_PATH)
message(FATAL_ERROR "lcov not found! Aborting...")
endif() # NOT LCOV_PATH
if(NOT GENHTML_PATH)
message(FATAL_ERROR "genhtml not found! Aborting...")
endif() # NOT GENHTML_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(LCOV_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES LCOV_EXCLUDES)
# Conditional arguments
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
endif()
# Setting up commands which will be run to generate coverage data.
# Cleanup lcov
set(LCOV_CLEAN_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory .
-b ${BASEDIR} --zerocounters
)
# Create baseline to make sure untouched files show up in the report
set(LCOV_BASELINE_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b
${BASEDIR} -o ${Coverage_NAME}.base
)
# Run tests
set(LCOV_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Capturing lcov counters and generating report
set(LCOV_CAPTURE_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b
${BASEDIR} --capture --output-file ${Coverage_NAME}.capture
)
# add baseline counters
set(LCOV_BASELINE_COUNT_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base
-a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total
)
# filter collected data to final coverage report
set(LCOV_FILTER_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove
${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info
)
# Generate HTML output
set(LCOV_GEN_HTML_CMD
${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o
${Coverage_NAME} ${Coverage_NAME}.info
)
if(${Coverage_SONARQUBE})
# Generate SonarQube output
set(GCOVR_XML_CMD
${GCOVR_PATH} --sonarqube ${Coverage_NAME}_sonarqube.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
)
set(GCOVR_XML_CMD_COMMAND
COMMAND ${GCOVR_XML_CMD}
)
set(GCOVR_XML_CMD_BYPRODUCTS ${Coverage_NAME}_sonarqube.xml)
set(GCOVR_XML_CMD_COMMENT COMMENT "SonarQube code coverage info report saved in ${Coverage_NAME}_sonarqube.xml.")
endif()
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to clean up lcov: ")
string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}")
message(STATUS "${LCOV_CLEAN_CMD_SPACED}")
message(STATUS "Command to create baseline: ")
string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}")
message(STATUS "${LCOV_BASELINE_CMD_SPACED}")
message(STATUS "Command to run the tests: ")
string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}")
message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to capture counters and generate report: ")
string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}")
message(STATUS "${LCOV_CAPTURE_CMD_SPACED}")
message(STATUS "Command to add baseline counters: ")
string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}")
message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}")
message(STATUS "Command to filter collected data: ")
string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}")
message(STATUS "${LCOV_FILTER_CMD_SPACED}")
message(STATUS "Command to generate lcov HTML output: ")
string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}")
message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}")
if(${Coverage_SONARQUBE})
message(STATUS "Command to generate SonarQube XML output: ")
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
message(STATUS "${GCOVR_XML_CMD_SPACED}")
endif()
endif()
# Setup target
add_custom_target(${Coverage_NAME}
COMMAND ${LCOV_CLEAN_CMD}
COMMAND ${LCOV_BASELINE_CMD}
COMMAND ${LCOV_EXEC_TESTS_CMD}
COMMAND ${LCOV_CAPTURE_CMD}
COMMAND ${LCOV_BASELINE_COUNT_CMD}
COMMAND ${LCOV_FILTER_CMD}
COMMAND ${LCOV_GEN_HTML_CMD}
${GCOVR_XML_CMD_COMMAND}
# Set output files as GENERATED (will be removed on 'make clean')
BYPRODUCTS
${Coverage_NAME}.base
${Coverage_NAME}.capture
${Coverage_NAME}.total
${Coverage_NAME}.info
${GCOVR_XML_CMD_BYPRODUCTS}
${Coverage_NAME}/index.html
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)
# Show where to find the lcov info report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
${GCOVR_XML_CMD_COMMENT}
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
endfunction() # setup_target_for_coverage_lcov
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr_xml(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
# GCVOR command.
function(setup_target_for_coverage_gcovr_xml)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
# Set up commands which will be run to generate coverage data
# Run tests
set(GCOVR_XML_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Running gcovr
set(GCOVR_XML_CMD
${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
)
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to generate gcovr XML coverage data: ")
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
message(STATUS "${GCOVR_XML_CMD_SPACED}")
endif()
add_custom_target(${Coverage_NAME}
COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
COMMAND ${GCOVR_XML_CMD}
BYPRODUCTS ${Coverage_NAME}.xml
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce Cobertura code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
)
endfunction() # setup_target_for_coverage_gcovr_xml
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr_html(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
# GCVOR command.
function(setup_target_for_coverage_gcovr_html)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
# Set up commands which will be run to generate coverage data
# Run tests
set(GCOVR_HTML_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Create folder
set(GCOVR_HTML_FOLDER_CMD
${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
)
# Running gcovr
set(GCOVR_HTML_CMD
${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
)
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to create a folder: ")
string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
message(STATUS "Command to generate gcovr HTML coverage data: ")
string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
message(STATUS "${GCOVR_HTML_CMD_SPACED}")
endif()
add_custom_target(${Coverage_NAME}
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
COMMAND ${GCOVR_HTML_FOLDER_CMD}
COMMAND ${GCOVR_HTML_CMD}
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce HTML code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
endfunction() # setup_target_for_coverage_gcovr_html
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_fastcov(
# NAME testrunner_coverage # New target name
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES testrunner # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude.
# NO_DEMANGLE # Don't demangle C++ symbols
# # even if c++filt is found
# SKIP_HTML # Don't create html report
# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths
# )
function(setup_target_for_coverage_fastcov)
set(options NO_DEMANGLE SKIP_HTML)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT FASTCOV_PATH)
message(FATAL_ERROR "fastcov not found! Aborting...")
endif()
if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH)
message(FATAL_ERROR "genhtml not found! Aborting...")
endif()
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (Patterns, not paths, for fastcov)
set(FASTCOV_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES})
list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES FASTCOV_EXCLUDES)
# Conditional arguments
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
endif()
# Set up commands which will be run to generate coverage data
set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
--search-directory ${BASEDIR}
--process-gcno
--output ${Coverage_NAME}.json
--exclude ${FASTCOV_EXCLUDES}
)
set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH}
-C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info
)
if(Coverage_SKIP_HTML)
set(FASTCOV_HTML_CMD ";")
else()
set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS}
-o ${Coverage_NAME} ${Coverage_NAME}.info
)
endif()
set(FASTCOV_POST_CMD ";")
if(Coverage_POST_CMD)
set(FASTCOV_POST_CMD ${Coverage_POST_CMD})
endif()
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):")
message(" Running tests:")
string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}")
message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}")
message(" Capturing fastcov counters and generating report:")
string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}")
message(" ${FASTCOV_CAPTURE_CMD_SPACED}")
message(" Converting fastcov .json to lcov .info:")
string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}")
message(" ${FASTCOV_CONVERT_CMD_SPACED}")
if(NOT Coverage_SKIP_HTML)
message(" Generating HTML report: ")
string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}")
message(" ${FASTCOV_HTML_CMD_SPACED}")
endif()
if(Coverage_POST_CMD)
message(" Running post command: ")
string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}")
message(" ${FASTCOV_POST_CMD_SPACED}")
endif()
endif()
# Setup target
add_custom_target(${Coverage_NAME}
# Cleanup fastcov
COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
--search-directory ${BASEDIR}
--zerocounters
COMMAND ${FASTCOV_EXEC_TESTS_CMD}
COMMAND ${FASTCOV_CAPTURE_CMD}
COMMAND ${FASTCOV_CONVERT_CMD}
COMMAND ${FASTCOV_HTML_CMD}
COMMAND ${FASTCOV_POST_CMD}
# Set output files as GENERATED (will be removed on 'make clean')
BYPRODUCTS
${Coverage_NAME}.info
${Coverage_NAME}.json
${Coverage_NAME}/index.html # report directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
)
set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.")
if(NOT Coverage_SKIP_HTML)
string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.")
endif()
# Show where to find the fastcov info report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG}
)
endfunction() # setup_target_for_coverage_fastcov
function(append_coverage_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
endfunction() # append_coverage_compiler_flags
# Setup coverage for specific library
function(append_coverage_compiler_flags_to_target name)
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
target_compile_options(${name} PRIVATE ${_flag_list})
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
target_link_libraries(${name} PRIVATE gcov)
endif()
endfunction()

23
scripts/coverage.sh Normal file
View File

@@ -0,0 +1,23 @@
#!/bin/bash
# This script is intended to be used in automated testing
# Specifically, in a Linux environment with certain packages installed
# If you want to use this script, please copy this file and make changes
# However, we DO NOT guarantee this script would work on every machine
: ${CC:=gcc}
: ${CXX:=g++}
BUILD_DIR=coverage_build
cmake \
-B $BUILD_DIR \
-DCOVERAGE=ON \
-DCMAKE_C_COMPILER=$CC \
-DCMAKE_CXX_COMPILER=$CXX \
cmake --build $BUILD_DIR
"./${BUILD_DIR}/ut_all"
cmake --build $BUILD_DIR --target ut_all_coverage

40
src/Drink.cpp Normal file
View File

@@ -0,0 +1,40 @@
//
// Created by User on 2024/10/29.
//
#include "Drink.hpp"
Drink::Drink(Production id) : Food(id){
MakeFood();
}
void Drink::MakeFood() {
switch (id) {
case Production::Cola:
ingredient = {Ingredients::Cola};
money = 28;
break;
case Production::Spirit:
ingredient = {Ingredients::Spirit};
money = 28;
break;
case Production::CaramelMilktea:
ingredient = {Ingredients::Caramel,Ingredients::Milktea};
money = 44;
break;
case Production::Latte:
ingredient = {Ingredients::Milk,Ingredients::Coffee};
money = 45;
break;
}
}
void Drink::MakeLarger(){
switch (id) {
case Production::CaramelMilktea:
break;
default:
ml = 750;
money+=10;
}
}
int Drink::GetMl(){
return ml;
}

16
src/Food.cpp Normal file
View File

@@ -0,0 +1,16 @@
//
// Created by User on 2024/10/29.
//
#include "Food.hpp"
Food::Food(Production id) : id(id) {}
Production Food::getId() const {
return id;
}
std::vector<Ingredients> Food::GetIngredient(){
return ingredient;
}
int Food::GetMoney() {
return money;
}

52
src/MainDish.cpp Normal file
View File

@@ -0,0 +1,52 @@
//
// Created by User on 2024/10/29.
//
#include "MainDish.hpp"
MainDish::MainDish(Production id) : Food(id){
MakeFood();
}
void MainDish::MakeFood() {
switch (id) {
case Production::PorkBurger:
ingredient = {Ingredients::PorkSteak,Ingredients::Lattuce,Ingredients::BurgerBread,Ingredients::Cheese};
money = 59;
break;
case Production::BeefBurger:
ingredient = {Ingredients::BeefSteak,Ingredients::Lattuce,Ingredients::BurgerBread,Ingredients::Cheese};
money = 69;
break;
case Production::FishBurger:
ingredient = {Ingredients::FishSteak,Ingredients::Lattuce,Ingredients::BurgerBread,Ingredients::Cheese};
money = 79;
break;
}
}
void MainDish::AddIngredients(std::vector<Ingredients> addtional){
this->addtional = addtional;
int add_mon = 0;
for(auto i:addtional){
switch (i) {
case Ingredients::PorkSteak:
add_mon+=20;
break;
case Ingredients::BeefSteak:
add_mon+=20;
break;
case Ingredients::FishSteak:
add_mon+=20;
break;
case Ingredients::Lattuce:
add_mon+=10;
break;
case Ingredients::Cheese:
add_mon+=10;
break;
default:
throw std::invalid_argument("Can't add the thing to here.");
}
}
money += add_mon;
}

55
src/OishiiPapa.cpp Normal file
View File

@@ -0,0 +1,55 @@
#include "OishiiPapa.hpp"
OishiiPapa::OishiiPapa() {}
int OishiiPapa::GetMoney() {
return money;
}
void OishiiPapa::SendOrder(Order order){
pipeline.push(order);
if(chest.size() >= 15){
return;
}
MakeDish();
}
void OishiiPapa::MakeDish() {
if(pipeline.empty()){
throw std::out_of_range("Pipeline is empty");
}
auto order = pipeline.front();
pipeline.pop();
Package pack;
auto product = order.GetProductInfo();
auto addtion = order.GetAddtionalInfo();
auto large = order.GetLargerInfo();
if(product[0] != Production::_NULL){
MainDish maindish(product[0]);
if(addtion.size()) maindish.AddIngredients(addtion);
pack.SetMainDish(maindish);
}
if(product[1] != Production::_NULL){
SideDish sideDish(product[1]);
if(large[0]) sideDish.MakeLarger();
pack.SetSideDish(sideDish);
}
if(product[2] != Production::_NULL){
Drink drink(product[2]);
if(large[1]) drink.MakeLarger();
pack.SetDrink(drink);
}
pack.CountMoney();
chest.push(pack);
}
Package OishiiPapa::Pickup() {
if(chest.empty()){
throw std::out_of_range("Chest is empty");
}
auto tmp = chest.front();
chest.pop();
if(chest.size() < 15 && !pipeline.empty()) {
MakeDish();
}
money += tmp.GetMoney();
return tmp;
}

20
src/Order.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include <Order.hpp>
Order::Order(std::vector<Production> product, std::vector<Ingredients> addtional, std::vector<bool> larger) {
this->addtional = addtional;
this->product = product;
this->larger = larger;
}
std::vector<Production> Order::GetProductInfo(){
return product;
}
std::vector<Ingredients> Order::GetAddtionalInfo(){
return addtional;
}
std::vector<bool> Order::GetLargerInfo(){
return larger;
}

32
src/Package.cpp Normal file
View File

@@ -0,0 +1,32 @@
//
// Created by User on 2024/10/29.
//
#include "Package.hpp"
Package::Package(){
}
void Package::CountMoney(){
if(maindish != NULL){
money += maindish->GetMoney();
}
if(sidedish != NULL){
money += sidedish->GetMoney();
}
if(drink != NULL){
money += drink->GetMoney();
}
if(sidedish && maindish && drink) money-=15;
}
int Package::GetMoney(){
return money;
}
void Package::SetDrink(Drink drink) {
this->drink = std::make_shared<Drink>(drink);
}
void Package::SetMainDish(MainDish maindish) {
this->maindish = std::make_shared<MainDish>(maindish);
}
void Package::SetSideDish(SideDish sidedish) {
this->sidedish = std::make_shared<SideDish>(sidedish);
}

37
src/SideDish.cpp Normal file
View File

@@ -0,0 +1,37 @@
//
// Created by User on 2024/10/29.
//
#include "SideDish.hpp"
SideDish::SideDish(Production id) : Food(id) {
MakeFood();
}
void SideDish::MakeFood() {
switch (id) {
case Production::Frenchfries:
ingredient = {Ingredients::FranchFries};
money = 44;
break;
case Production::Nugget:
ingredient = {Ingredients::ChickenNugget};
money = 44;
break;
case Production::Salad:
ingredient = {Ingredients::Salad};
money = 59;
break;
}
}
void SideDish::MakeLarger(){
switch (id) {
case Production::Salad:
break;
default:
money+=15;
type = SideDishType::BIG;
}
}
SideDishType SideDish::GetType() {return type;}

128
test/ut_Food.cpp Normal file
View File

@@ -0,0 +1,128 @@
#include <gtest/gtest.h>
#include <vector>
#include "MainDish.hpp"
#include "SideDish.hpp"
#include "Drink.hpp"
TEST(MAINDISH_TEST, check_maindish_should_have_correct_id){
MainDish mainDish(Production::BeefBurger);
Production product = mainDish.getId();
ASSERT_EQ(product,Production::BeefBurger);
}
TEST(MAINDISH_TEST, check_maindish_should_have_correct_money){
MainDish mainDish(Production::FishBurger);
int price = mainDish.GetMoney();
ASSERT_EQ(price,79);
}
TEST(MAINDISH_TEST, check_maindish_should_have_correct_ingredients){
MainDish mainDish(Production::FishBurger);
auto ingredients = mainDish.GetIngredient();
ASSERT_EQ(ingredients[0],Ingredients::FishSteak);
ASSERT_EQ(ingredients[1],Ingredients::Lattuce);
ASSERT_EQ(ingredients[2],Ingredients::BurgerBread);
ASSERT_EQ(ingredients[3],Ingredients::Cheese);
}
TEST(MAINDISH_TEST, check_maindish_should_throw_invalid_argument_for_additional_food){
MainDish mainDish(Production::FishBurger);
std::vector<Ingredients> addition = {Ingredients::Lattuce,Ingredients::Caramel};
ASSERT_THROW(mainDish.AddIngredients(addition),std::invalid_argument);
}
TEST(MAINDISH_TEST, check_maindish_should_throw_invalid_argument_for_additional_food_two){
MainDish mainDish(Production::FishBurger);
std::vector<Ingredients> addition = {
Ingredients::Cola,
Ingredients::Caramel,
Ingredients::ChickenNugget,
Ingredients::Lattuce,
Ingredients::Milk,
Ingredients::Milktea,
Ingredients::Spirit,
};
ASSERT_THROW(mainDish.AddIngredients(addition),std::invalid_argument);
}
TEST(MAINDISH_TEST, check_maindish_should_have_correct_money_after_get_addtional_food){
MainDish mainDish(Production::FishBurger);
std::vector<Ingredients> addition = {Ingredients::Lattuce,Ingredients::FishSteak};
mainDish.AddIngredients(addition);
int price = mainDish.GetMoney();
ASSERT_EQ(price,109);
}
TEST(MAINDISH_TEST, check_maindish_should_have_correct_money_after_get_addtional_food_two){
MainDish mainDish(Production::FishBurger);
std::vector<Ingredients> addition = {
Ingredients::Lattuce,
Ingredients::FishSteak,
Ingredients::BeefSteak,
Ingredients::Cheese,
};
mainDish.AddIngredients(addition);
int price = mainDish.GetMoney();
ASSERT_EQ(price,139);
}
TEST(SIDEDISH_TEST, check_sidedish_should_have_correct_id){
SideDish sidedish(Production::Frenchfries);
Production product = sidedish.getId();
ASSERT_EQ(product,Production::Frenchfries);
}
TEST(SIDEDISH_TEST, check_sidedish_is_small){
SideDish sidedish(Production::Nugget);
SideDishType product = sidedish.GetType();
ASSERT_EQ(product,SideDishType::SMALL);
}
TEST(SIDEDISH_TEST, check_sidedish_can_make_larger){
SideDish sidedish(Production::Frenchfries);
sidedish.MakeLarger();
SideDishType product = sidedish.GetType();
ASSERT_EQ(product,SideDishType::BIG);
}
TEST(SIDEDISH_TEST, check_sidedish_make_larger_maintain_same){
SideDish sidedish(Production::Salad);
sidedish.MakeLarger();
SideDishType product = sidedish.GetType();
ASSERT_EQ(product,SideDishType::SMALL);
}
TEST(DRINK_TEST,check_drink_have_correct_id){
Drink drink(Production::Latte);
Production product = drink.getId();
ASSERT_EQ(product,Production::Latte);
}
TEST(DRINK_TEST,check_drink_have_correct_price){
Drink drink(Production::CaramelMilktea);
int price = drink.GetMoney();
ASSERT_EQ(price,44);
}
TEST(DRINK_TEST,check_drink_make_larger){
Drink drink(Production::Cola);
drink.MakeLarger();
int cc = drink.GetMl();
ASSERT_EQ(cc,750);
}

211
test/ut_Oishiipapa.cpp Normal file
View File

@@ -0,0 +1,211 @@
#include "OishiiPapa.hpp"
#include "Order.hpp"
#include <gtest/gtest.h>
#include <Ingredients.hpp>
TEST(OISHIIPAPA_TEST, check_papa_should_throw_exception_for_chest){
OishiiPapa ohpapa;
ASSERT_THROW(ohpapa.Pickup(),std::out_of_range);
}
TEST(OISHIIPAPA_TEST, check_papa_should_throw_exception_for_pipeline){
OishiiPapa ohpapa;
ASSERT_THROW(ohpapa.MakeDish(),std::out_of_range);
}
TEST(OISHIIPAPA_TEST, check_papa_should_take_care_of_pickup){
//Make Object Oishii Papa.
OishiiPapa ohpapa;
//Production.
std::vector<Production> product1 = {Production::PorkBurger,Production::_NULL,Production::_NULL};
std::vector<Production> product2 = {Production::FishBurger,Production::_NULL,Production::_NULL};
std::vector<Production> product3 = {Production::BeefBurger,Production::_NULL,Production::_NULL};
std::vector<Production> product4 = {Production::_NULL,Production::Frenchfries,Production::_NULL};
std::vector<Production> product5 = {Production::_NULL,Production::Nugget,Production::_NULL};
std::vector<Production> product6 = {Production::_NULL,Production::Salad,Production::_NULL};
std::vector<Production> product7 = {Production::_NULL,Production::_NULL,Production::Spirit};
std::vector<Production> product8 = {Production::_NULL,Production::_NULL,Production::Cola};
std::vector<Production> product9 = {Production::_NULL,Production::_NULL,Production::CaramelMilktea};
std::vector<Production> product10 = {Production::_NULL,Production::_NULL,Production::Latte};
std::vector<Production> product11 = {Production::PorkBurger,Production::_NULL,Production::Cola};
std::vector<Production> product12 = {Production::FishBurger,Production::Frenchfries,Production::CaramelMilktea};
std::vector<Production> product13 = {Production::BeefBurger,Production::Nugget,Production::Cola};
std::vector<Production> product14 = {Production::FishBurger,Production::Salad,Production::Spirit};
std::vector<Production> product15 = {Production::BeefBurger,Production::Salad,Production::Latte};
std::vector<Production> product16 = {Production::PorkBurger,Production::Nugget,Production::Cola};
std::vector<Production> product17 = {Production::PorkBurger,Production::Frenchfries,Production::_NULL};
//Addtional Ingredients.
std::vector<Ingredients> additional1 = {Ingredients::Lattuce,Ingredients::Cheese};
std::vector<Ingredients> additional2 = {Ingredients::PorkSteak,Ingredients::Cheese};
std::vector<Ingredients> additional3 = {Ingredients::FishSteak,Ingredients::Lattuce};
std::vector<Ingredients> additional4 = {Ingredients::BeefSteak,Ingredients::BeefSteak};
std::vector<Ingredients> additional5 = {Ingredients::Lattuce,Ingredients::PorkSteak,Ingredients::Cheese};
std::vector<Ingredients> additional6 = {Ingredients::Lattuce,Ingredients::PorkSteak,Ingredients::FishSteak};
std::vector<Ingredients> additional7 = {Ingredients::Lattuce,Ingredients::BeefSteak};
std::vector<Ingredients> additional8 = {};
//If larger.
std::vector<bool> condition1 = {true, true};
std::vector<bool> condition2 = {true, false};
std::vector<bool> condition3 = {false, true};
std::vector<bool> condition4 = {false, false};
//Make order object.
Order OrderList1(product1,additional1,condition4);
Order OrderList2(product2,additional2,condition4);
Order OrderList3(product3,additional3,condition4);
Order OrderList4(product4,additional8,condition2);
Order OrderList5(product5,additional8,condition2);
Order OrderList6(product6,additional8,condition4);
Order OrderList7(product7,additional8,condition4);
Order OrderList8(product8,additional8,condition3);
Order OrderList9(product9,additional8,condition4);
Order OrderList10(product10,additional8,condition3);
Order OrderList11(product11,additional1,condition3);
Order OrderList12(product12,additional2,condition2);
Order OrderList13(product13,additional3,condition1);
Order OrderList14(product14,additional4,condition3);
Order OrderList15(product15,additional5,condition3);
Order OrderList16(product16,additional6,condition4);
Order OrderList17(product16,additional7,condition1);
Order OrderList18(product16,additional8,condition1);
Order OrderList19(product15,additional8,condition3);
Order OrderList20(product17,additional1,condition2);
//Test.
ohpapa.SendOrder(OrderList1);
ohpapa.SendOrder(OrderList2);
ohpapa.SendOrder(OrderList3);
ohpapa.SendOrder(OrderList4);
ohpapa.SendOrder(OrderList5);
ohpapa.SendOrder(OrderList6);
ohpapa.SendOrder(OrderList7);
ohpapa.SendOrder(OrderList8);
ohpapa.SendOrder(OrderList9);
ohpapa.SendOrder(OrderList10);
ohpapa.SendOrder(OrderList11);
ohpapa.SendOrder(OrderList12);
ohpapa.SendOrder(OrderList13);
ohpapa.SendOrder(OrderList14);
ohpapa.SendOrder(OrderList15);
ohpapa.SendOrder(OrderList16);
ohpapa.SendOrder(OrderList17);
ohpapa.SendOrder(OrderList18);
ohpapa.SendOrder(OrderList19);
ohpapa.SendOrder(OrderList20);
//Result.
Package pack;
MainDish pb(Production::PorkBurger);
pb.AddIngredients(additional1);
pack.SetMainDish(pb);
pack.CountMoney();
auto tmp = ohpapa.Pickup();
ASSERT_EQ(tmp.GetMoney(),pack.GetMoney());
ASSERT_EQ(ohpapa.GetMoney(),pack.GetMoney());
}
TEST(OISHIIPAPA_TEST, check_papa_should_take_care_of_pickup_part2){
//Make Object Oishii Papa.
OishiiPapa ohpapa;
//Production.
std::vector<Production> product1 = {Production::PorkBurger,Production::_NULL,Production::_NULL};
std::vector<Production> product2 = {Production::FishBurger,Production::_NULL,Production::_NULL};
std::vector<Production> product3 = {Production::BeefBurger,Production::_NULL,Production::_NULL};
std::vector<Production> product4 = {Production::_NULL,Production::Frenchfries,Production::_NULL};
std::vector<Production> product5 = {Production::_NULL,Production::Nugget,Production::_NULL};
std::vector<Production> product6 = {Production::_NULL,Production::Salad,Production::_NULL};
std::vector<Production> product7 = {Production::_NULL,Production::_NULL,Production::Spirit};
std::vector<Production> product8 = {Production::_NULL,Production::_NULL,Production::Cola};
std::vector<Production> product9 = {Production::_NULL,Production::_NULL,Production::CaramelMilktea};
std::vector<Production> product10 = {Production::_NULL,Production::_NULL,Production::Latte};
std::vector<Production> product11 = {Production::PorkBurger,Production::_NULL,Production::Cola};
std::vector<Production> product12 = {Production::FishBurger,Production::Frenchfries,Production::CaramelMilktea};
std::vector<Production> product13 = {Production::BeefBurger,Production::Nugget,Production::Cola};
std::vector<Production> product14 = {Production::FishBurger,Production::Salad,Production::Spirit};
std::vector<Production> product15 = {Production::BeefBurger,Production::Salad,Production::Latte};
std::vector<Production> product16 = {Production::PorkBurger,Production::Nugget,Production::Cola};
std::vector<Production> product17 = {Production::PorkBurger,Production::Frenchfries,Production::_NULL};
//Addtional Ingredients.
std::vector<Ingredients> additional1 = {Ingredients::Lattuce,Ingredients::Cheese};
std::vector<Ingredients> additional2 = {Ingredients::PorkSteak,Ingredients::Cheese};
std::vector<Ingredients> additional3 = {Ingredients::FishSteak,Ingredients::Lattuce};
std::vector<Ingredients> additional4 = {Ingredients::BeefSteak,Ingredients::BeefSteak};
std::vector<Ingredients> additional5 = {Ingredients::Lattuce,Ingredients::PorkSteak,Ingredients::Cheese};
std::vector<Ingredients> additional6 = {Ingredients::Lattuce,Ingredients::PorkSteak,Ingredients::FishSteak};
std::vector<Ingredients> additional7 = {Ingredients::Lattuce,Ingredients::BeefSteak};
std::vector<Ingredients> additional8 = {};
//If larger.
std::vector<bool> condition1 = {true, true};
std::vector<bool> condition2 = {true, false};
std::vector<bool> condition3 = {false, true};
std::vector<bool> condition4 = {false, false};
//Make order object.
Order OrderList1(product1,additional1,condition4);
Order OrderList2(product2,additional2,condition4);
Order OrderList3(product3,additional3,condition4);
Order OrderList4(product4,additional8,condition2);
Order OrderList5(product5,additional8,condition2);
Order OrderList6(product6,additional8,condition4);
Order OrderList7(product7,additional8,condition4);
Order OrderList8(product8,additional8,condition3);
Order OrderList9(product9,additional8,condition4);
Order OrderList10(product10,additional8,condition3);
Order OrderList11(product11,additional1,condition3);
Order OrderList12(product12,additional2,condition2);
Order OrderList13(product13,additional3,condition1);
Order OrderList14(product14,additional4,condition3);
Order OrderList15(product15,additional5,condition3);
Order OrderList16(product16,additional6,condition4);
Order OrderList17(product16,additional7,condition1);
Order OrderList18(product16,additional8,condition1);
Order OrderList19(product15,additional8,condition3);
Order OrderList20(product17,additional1,condition2);
//Test.
ohpapa.SendOrder(OrderList1);
ohpapa.SendOrder(OrderList2);
ohpapa.SendOrder(OrderList3);
ohpapa.SendOrder(OrderList4);
ohpapa.SendOrder(OrderList5);
ohpapa.SendOrder(OrderList6);
ohpapa.SendOrder(OrderList7);
ohpapa.SendOrder(OrderList8);
ohpapa.SendOrder(OrderList9);
ohpapa.SendOrder(OrderList10);
ohpapa.SendOrder(OrderList11);
ohpapa.SendOrder(OrderList12);
ohpapa.SendOrder(OrderList13);
ohpapa.SendOrder(OrderList14);
ohpapa.SendOrder(OrderList15);
ohpapa.SendOrder(OrderList16);
ohpapa.SendOrder(OrderList17);
ohpapa.SendOrder(OrderList18);
ohpapa.SendOrder(OrderList19);
ohpapa.SendOrder(OrderList20);
//Result.
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ohpapa.Pickup();
ASSERT_EQ(ohpapa.GetMoney(),2317);
}

51
test/ut_Package.cpp Normal file
View File

@@ -0,0 +1,51 @@
#include <gtest/gtest.h>
#include <vector>
#include "Package.hpp"
TEST(PACKAGE_TEST, check_package_should_have_correct_money){
Package pack;
MainDish maindish(Production::PorkBurger);
SideDish sidedish(Production::Frenchfries);
pack.SetMainDish(maindish);
pack.SetSideDish(sidedish);
pack.CountMoney();
int price = pack.GetMoney();
ASSERT_EQ(price,103);
}
TEST(PACKAGE_TEST, check_package_should_have_correct_money_for_pack){
Package pack;
MainDish maindish(Production::PorkBurger);
SideDish sidedish(Production::Frenchfries);
Drink drink(Production::Cola);
drink.MakeLarger();
pack.SetMainDish(maindish);
pack.SetSideDish(sidedish);
pack.SetDrink(drink);
pack.CountMoney();
int price = pack.GetMoney();
ASSERT_EQ(maindish.GetMoney(),59);
ASSERT_EQ(sidedish.GetMoney(),44);
ASSERT_EQ(drink.GetMoney(),38);
ASSERT_EQ(price,126);
}
TEST(PACKAGE_TEST, check_package_should_have_correct_money_for_only_a_thing){
Package pack;
MainDish maindish(Production::PorkBurger);
pack.SetMainDish(maindish);
pack.CountMoney();
int price = pack.GetMoney();
ASSERT_EQ(maindish.GetMoney(),59);
ASSERT_EQ(price,59);
}