• (nodebb)

    No comments yet. People are still trying to read the code snippet.

  • RLB (unregistered)

    The saddest part is, it probably isn't even any more efficient than if it'd been written legibly.

  • shcode (unregistered)

    well, at least the return type os named correcly.

    it surely did result in damage to the reader

  • LCrawford (unregistered)

    The only thing missing is adding a recursive call to progress() for further confusion with the value progress.

  • Dave Hemming (unregistered)

    Is there an IDE add-on that converts Ternaries to properly nested IF THEN ELSE ?

  • Anonymous (unregistered)

    To add to the horror, once you replace all those ternary by if / else, you can see the author probably didn't even tried to make a truth table

    DamageResult progress(UUID uuid, double progress, boolean auto) { if(this.isLooted()) { return DamageResult.ALREADY_LOOTED; } else { if(this.thief == null) { return this.makeProgress(uuid, progress); } else { if(this.challenger == null) { if (this.thief.equals(uuid)) { if (auto) { if (this.ticksSinceLastThiefHit >= this.getConfig().getLootTickRate()) { return this.makeProgress(uuid, progress); } else { return DamageResult.AUTO_NOT_YET; } } else { if (this.ticksSinceLastThiefHit >= this.getConfig().getClickRateCap()) { return this.makeProgress(uuid, progress); } else { return DamageResult.TOO_QUICK; } } } else { return this.makeChallengeProgress(uuid, progress, true); } } else { if (this.thief.equals(uuid) || this.challenger.equals(uuid)) { if (auto) { return DamageResult.NO_AUTO_CHALLENGE; } else { if (( this.thief.equals(uuid) ? this.ticksSinceLastThiefHit : this.ticksSinceLastChallengerHit ) >= this.getConfig().getChallengeClickRateCap() ) { return this.makeChallengeProgress(uuid, progress, false); } else { return DamageResult.TOO_QUICK; } } } else { return DamageResult.CHALLENGE_IN_PROGRESS; } } } } }

  • (nodebb) in reply to Anonymous

    To add to the horror, once you replace all those ternary by if / else, you can see the author probably didn't even tried to make a truth table

    There's your WTF. ^^^^ Right there

  • Argle (unregistered)

    In all fairness to the original programmer, we should probably note that this probably began as:

    DamageResult progress() { return this.isLooted() ? DamageResult.ALREADY_LOOTED : DamageResult.CHALLENGE_IN_PROGRESS; }

  • Bappo (unregistered)

    Assembler programming wasn't so bad, after all.

  • JimboJambo (unregistered)

    Tried to make sense of it, at this point i think it's impossible to guess what this does and where it's supposed to go. I'm also pretty sure i messed up trying to unwind all the ternary hell, but here it goes

    //I'm still not sure if this is a battle or a lockpicking minigame... DamageResult progress(UUID uuid, double progress, boolean auto) { if(this.isLooted()) { return DamageResult.ALREADY_LOOTED; }

    if(this.thief == null) {
    	return this.makeProgress(uuid, progress)
    }
    
    boolean thiefCanActAgain = this.ticksSinceLastThiefHit >= this.getConfig().getLootTickRate();
    boolean thiefIsUuid = this.thief.equals(uuid);
    boolean challengerIsUuid = this.challenger.equals(uuid);
    boolean ticksSinceLastUuidHit = (thiefIsUuid ? this.ticksSinceLastThiefHit : this.ticksSinceLastChallengerHit)
    
    if(this.challenger == null) {
    	if(thiefIsUuid) {
    		if(auto) {
    			if(thiefCanStealAgain) {
    				return this.makeProgress(uuid, progress)
    			} else {
    				return DamageResult.AUTO_NOT_YET
    			}
    		} else {
    			if(thiefCanStealAgain) {
    				return this.makeProgress(uuid, progress)
    			} else {
    				return DamageResult.TOO_QUICK
    			}
    		}
    	} else {
    		return this.makeChallengeProgress(uuid, progress, true);
    	}
    } else {
    	if(thiefIsUuid || challengerIsUuid) {
    		if(auto) {
    			retrun DamageResult.NO_AUTO_CHALLENGE;
    		} else {
    			if(ticksSinceLastUuidHit >= this.getConfig().getChallengeClickRateCap()) {
    				return this.makeChallengeProgress(uuid, progress, false);
    			} else {
    				return DamageResult.TOO_QUICK;
    			}
    		}
    	} else {
    		return DamageResult.CHALLENGE_IN_PROGRESS
    	}
    }
    

    }

  • Legacy Warrior (unregistered)

    Here's my attempt at a rewrite. It still utilizes a few ternaries but in a much saner way. It also negates a few of the conditionals to supply early ejection points and avoid pyramid programming. This should honestly be refactored into at least two separate methods but I'm done here.

    DamageResult progress(UUID uuid, double progress, boolean auto) { if (this.isLooted()) return DamageResult.ALREADY_LOOTED;

    if (this.thief == null)
        return this.makeProgress(uuid, progress);
    
    if (this.challenger == null) {
        if (!this.thief.equals(uuid))
            return this.makeChallengeProgress(uuid, progress, true);
    
            if (auto) {
                const bool canAct = this.ticksSinceLastThiefHit >= this.getConfig().getLootTickRate();
                return canAct ? this.makeProgress(uuid, progress) : DamageResult.AUTO_NOT_YET;
            } else {
                const bool canAct = this.ticksSinceLastThiefHit >= this.getConfig().getClickRateCap();                
                return canAct ? this.makeProgress(uuid, progress) : DamageResult.TOO_QUICK;
            }
    } else {
        if (!(this.thief.equals(uuid) || this.challenger.equals(uuid))) 
            return DamageResult.CHALLENGE_IN_PROGRESS;
    
        if (auto)
            return DamageResult.NO_AUTO_CHALLENGE;
    
        const short ticks = (this.thief.equals(uuid) ? this.ticksSinceLastThiefHit : this.ticksSinceLastChallengerHit);
        if (ticks >= this.getConfig().getChallengeClickRateCap()) {
            return this.makeChallengeProgress(uuid, progress, false);
        } else {
            return DamageResult.TOO_QUICK;
        }            
    }
    

    }

  • (nodebb)

    Credit to the developer, they did a good job naming their variables.

  • Barf4Eva (unregistered)

    Here is one: https://documentation.devexpress.com/CodeRushForRoslyn/115431/Refactoring-Assistance/Compress-to-Expand-Ternary-Expression

    Here are a few other solutions: https://stackoverflow.com/questions/8891481/convert-ternary-conditional-operators-into-if-statements

    An online one: http://converter.website-dev.eu/

  • I Saw a Robot (unregistered) in reply to JimboJambo

    And your expansion shows that it's not the use of ternaries that makes this a WTF, but the complete mess of logic therein.

  • Chris (unregistered) in reply to Barf4Eva

    I want to know* how those extensions for turning ternaries into if-elses go on this shambles. They should at least be using this as a test case.

    • But don't want to know badly enough to actually try.
  • Why Do I Even Try (unregistered)
      if (this.isLooted()) {
    	return DamageResult.ALREADY_LOOTED
      } 
    
      if (this.thief == null) {
    	return this.makeProgress(uuid, progress)
      } 
      var isTheif = this.thief.equals(uuid);
    	
      if (this.challenger == null) {
    	if (!isTheif) {
    		return this.makeChallengeProgress(uuid, progress, true)
    	}
    	
    	var rate = auto ? 
    		this.getConfig().getLootTickRate() :
    		this.getConfig().getClickRateCap()
    	
    	if (this.ticksSinceLastThiefHit >= rate) {
    		return this.makeProgress(uuid, progress)
    	}
    	
    	return auto ? DamageResult.AUTO_NOT_YET : DamageResult.TOO_QUICK;
    	
      } else {
    	if (!isTheif && !this.challenger.equals(uuid)) {
    		return DamageResult.CHALLENGE_IN_PROGRESS;
    	}
    	
    	if (auto) {
    		return DamageResult.NO_AUTO_CHALLENGE
    	} 
    	
    	var hit = isTheif ?
    		this.ticksSinceLastThiefHit :
    		this.ticksSinceLastChallengerHit
    	
    	if (hit >= this.getConfig().getChallengeClickRateCap()) {
    		return this.makeChallengeProgress(uuid, progress, false)
    	}
    	return DamageResult.TOO_QUICK
      }
    
  • (nodebb)

    When did TDWTF become a forum for submitting bad code and asking members to fix it?

  • David Mårtensson (unregistered) in reply to Dave Hemming

    Visual Studio 2017 and later, especially together with ReSharper from JetBrains has many such auto convert helpers to change between different ways to write the same code.

  • cactusheid (unregistered)

    I used to work at a games studio. I recognize this type of quality code that is produced weeks into a 996-type crunch cycle! (12+ hrs/day, 6 days/wk)...

  • (nodebb)

    Hello, everyone. The code snippet in this article is actually one of my own.

    I noticed that a method I had didn't have anything stopping me from turning it into a large ternary and, once done, shared it on a public Discord chat with some friends as a joke.

    I can assure you that this code never made it into production!

    If you want to view it in it's "unfucked" form, here's the gist I made when showing my friend: https://gist.github.com/FerusGrim/b740202598b729aa421a72938934a001

  • Feeling lucky (unregistered)

    It could be worse. In PHP

    return this.isLooted() ? DamageResult.ALREADY_LOOTED : this.thief == null ? this.makeProgress(uuid, progress) : this.challenger == null ? ..

    it evaluates as

    return (( (this.isLooted() ? DamageResult.ALREADY_LOOTED : this.thief == null) ? this.makeProgress(uuid, progress) : this.challenger == null )) ? ..

  • Paula J. Bean (unregistered)

    I see this often in spreadsheets, where one is forced to use IF as a function: =IF(condcell; true-clause false-clause), where true-clause and/or false-clause are nested with further IF()'s. Also, Excel is not an exchange format.

Leave a comment on “Whose Tern is it to Play?”

Log In or post as a guest

Replying to comment #:

« Return to Article