0

Firstly, because the code I am using is big so here is the link to the code.

I have this function that runs other functions if a specific input is given:

allowed_commands = ['help', 'joblist', 'job', 'jobresign', 'work', 'bal', 'balance', 'dep', 'deposit', 'with', 'withdraw', 'fish', 'hunt', 'shop', 'buy', 'sell', 'hunt', 'fish', 'multiply']

def gamePlay():
    while True:
        command = input(f"{bright_green}Command (type [help] to see list of all commands):\n>> ")
        while command in allowed_commands:
            # <-- Display Rules -->
            if command == 'help':
                rules()
                break

            # <-- Display Jobs -->
            elif command == 'joblist':
                joblist_function()
                break

            # <-- Get Jobs -->
            elif command == 'job' and working == False:
                job_funtion()
                break

            elif command == 'job' and working == True:
                print(f"\n{red}You are already doing a job. You can't work on two jobs,that is dumb...\n")
                break

            # <-- Resign Job -->
            elif command == 'jobresign':
                job_resign()
                break

            # <-- Work -->
            elif command == 'work' and working == True:
                work()
                break
            
            elif command == "work" and working == False:
                print(f"{red}\nLOL, you don't have a job, how you gonna work?\n")
                break

            # <-- Deposit -->
            elif command == 'dep' or command == 'deposit' and deposit_allowed != deposited:
                dep_money()
                break

            elif command == 'dep' or command == 'deposit' and deposit_allowed == deposited:
                print("You have a full bank kiddo...")
                break

            # <-- Balance -->
            elif command == 'bal' or command == 'balance':
                display_balance()
                break

            # <-- Withdraw -->
            elif command == 'with' or command == 'withdraw' and deposited != 0:
                withdraw_money()
                break
            
            elif command == 'with' or command == 'withdraw' and deposited == 0:
                print(f"{red}\nNo money deposited. What are you even trying to wothdraw LOL?\n")
                break

            elif command == 'shop':
                shop()
                break

            elif command == 'beg':
                beg()
                break
def beg():
    global money
    random_number2 = random.choice([0, 1, 2])
    random_money = random.choice(range(100, 500))

    if random_number2 == 1:
        print("Ewwww beggar. No stonks for u")
    
    if random_number2 == 2:
        print(f"Mr.beggar, you can have ⏣ {random_money}.")
        money += random_money

But the tooltip on the green line under the function says "Cyclomatic complexity too high: 17 (threshold 15)". enter image description here

Normally, this would work in my code even though the complexity was up to 30. But the code after the last elif is not working. Even when I input 'beg', the function doesn’t run:

Command (type [help] to see list of all commands):
>> beg
Command (type [help] to see list of all commands):
>> beg
Command (type [help] to see list of all commands):
>> 

Why is this happening and how can I solve it?

OldWizard007
  • 370
  • 1
  • 8
  • Please reread [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). We need `allowed_commands` and `beg()` at the very least in order to help. Consider converting this large `if-else` block to use a `dict` in order to decide which function to execute. It won't help with your cyclomatic complexity warning, but it is the standard practice in Python for what would be a `switch` block in many other languages. – Michael Ruth Apr 04 '21 at 01:28
  • How will I be able to use dict in this case. I will re-edit this without the function and the list – OldWizard007 Apr 04 '21 at 01:30
  • This error is not familiar to me, but i think replacing "elif" by "if" would fix the problem. Anyway, you break the loop so replacing will not change your code behavior. – Fredericka Apr 04 '21 at 01:30
  • @GenisBillionaire, I don't think you understand: tooltip warnings in your IDE have nothing to do with how the code executes. There is no exception here, something else is going on and we need to see the rest of the referenced code in order to help. A `dict` will not solve this issue. – Michael Ruth Apr 04 '21 at 01:33
  • Ok I will add the needed stuff – OldWizard007 Apr 04 '21 at 01:34
  • Added the required resources @MichaelRuth – OldWizard007 Apr 04 '21 at 01:39
  • `"beg"` is not in `allowed_commands`. This is why nothing happens when you run your code. – Michael Ruth Apr 04 '21 at 01:41

2 Answers2

2

According to sonarQube docs,

Cyclomatic Complexity calculated based on the number of paths through the code. Whenever the control flow of a function splits, the complexity counter gets incremented by one. Each function has a minimum complexity of 1. This calculation varies slightly by language because keywords and functionalities do.

Although this Cyclomatic complexity could be vary based on the language, normally, loops and conditions together form an Cyclomatic complexity of 30. With the summing up the following keywords we could estimate the Cyclomatic complexity as 30 (Note that the real algorithm may be different).

    while 
        while  
            if ... 
            elif ... 
            elif ... and ... 
            elif ... and ...  
            elif ... 
            elif ... and ... 
            elif ... and ... 
            elif ... or  ... and ... 
            elif ... or  ... and ... 
            elif ... or  ... 
            elif ... or  ... and ... 
            elif ... or  ... and ... 
            elif ... 
            elif ... 

Although a higher Cyclomatic Complexity not a good practice in the code, it is only an warning and your code will compile as usual.

In your case, the issue which doesn't execute your beg command is that, beg is not present in your allowed_commands.

Tharindu Sathischandra
  • 1,654
  • 1
  • 15
  • 37
1

You can use dictionaries like this:

{
    'help': rules,
    'joblist': joblist_function,
}[command]()

But you can also do some refactoring like this:

from typing import Callable, Dict


class Game:
    def __init__(self) -> None:
        self.deposit_allowed = 1000
        self.deposited = 0

    def play(self) -> None:
        commands = self._get_commands()

        while True:
            command = input(f"{bright_green}Command (type [help] to see list of all commands):\n>> ")

            if command not in commands:
                print('Wrong command!')
                continue

            commands[command]()

    def _get_commands(self) -> Dict[str, Callable[[], None]]:
        return {
            'help': self._rules,
            'joblist': self._joblist_function,
            'deposit': self._deposit_money,
            'dep': self._dep_money,
            # ...
        }

    def _rules(self) -> None:
        pass

    def _joblist_function(self) -> None:
        pass

    def _deposit_money(self) -> None:
        if self.deposit_allowed == self.deposited:
            print("You have a full bank kiddo...")
            return

        self._dep_money()

    def _dep_money(self) -> None:
        pass


Game().play()
ADR
  • 1,255
  • 9
  • 20