Assignment - Breeding Frontend

Yeah thats a good solution!

@thecil @REGO350 @kenn.eth @Bhujanga
I just recently asked for some help - I found the chat place for the Catalogue.

I have made some progress but now after looking at the code, I think I am maybe way far off.

If anyone can look at my Catalogue HTML and JS and let me know if I am close or not…would appreciate it.

https://github.com/brlojam4932/myCryptoKitties_master.git

…I still think the video or the lesson should be included

1 Like

Hey Bhujanga, nice work!
I was looking at your code, what is substring? Example:

////////////////// SORRY - I REMEMBER NOW- NEVER MIND ///////////////////

let bodyDna = bearDetails.substring(0, 2);
      //  console.log("BODYDNA" + bodyDna);
        let mouthDna = bearDetails.substring(2, 4);

and what do the numbers represent?

1 Like

the numbers indicate where the string will be “cut”. Have a look here for the definition of the function

2 Likes

Het @ol_frank thats great! Just use position absolute inside position relative DIV to preserve the same box.

example:

<div style="position:relative">
          <div style="position:Absolute" class="catBox"></div>
</div>

Will be much easier if you play with this styles and positions with the console from the browser window. You can add, remove and modify until you get it as you want.

1 Like

Ahh yes, thank you @kenn.eth.

Any chance you can have a look at why my cats aren’t rendering colors and animations in the catalogue page. I thought i did everything required but it doesn’t seem to be working.

Appreciate the help :star_struck:

So i am currently trying to render my cats on my catalogue.html page but as you can see the unique colours and attributes aren’t being rendered like they are supposed to.

I am not sure why as the DNA string is available on page and in the console. I’m guessing i’m missing something but not too sure what it is.

You can see from the screenshot that the colors of the cat are being taken from the hardcoded colors in the cats.css file. And im not sure how to point it to the buildCat and showCat js files.

Would appreciate someone having a look into it if they have time.
The relevant files are:

showCats.js
//append cat on catalogue page
function appendCat(dna, id, gen){

    var catDna = catDNA(dna);
    catContainer(id);
    renderCat(catDna, id);
    // $('#catview' + id).attr('onclick', 'go_to("marketplace.html?catId=' + id + '")')
    $('#catDNA' + id).html(`
    <span class="badge badge-light"><h4 class="tsp-2 m-0"><b>GEN:</b>`+ gen + `</h4></span>
    <br>
    <span class="badge badge-light"><h4 class="tsp-2 m-0"><b>DNA:</b>`+ dna + `</h4></span>`)
}


//append cat for breeding
function breedAppend(dna, id, gen, gender){
    var catDna = catDna(dna);
    catBox(id);
    renderCat(catDna, id);
    $('#catDNA' + id).html(`
    <span class="badge badge-light"><h4 class="tsp-2 m-0"><b>GEN:</b>`+ gen + `</h4></span>
    <br>
    <span class="badge badge-light"><h4 class="tsp-2 m-0"><b>DNA:</b>`+ dna + `</h4></span>`)

    $('#catview' + id).attr('onclick', 'selectBreed("' + dna + '","' + id + '","' + gen + '","' + gender + '")')

}

function selectBreed(dna, id, gen, gender){
    var catDna = catDna(dna);
    var body = catBody(gender);
    var cattributes = cattributes(gender)
    $("#cattributes" + gender).html(cattributes)
    $('#' + gender).html(body);

    renderCat(catDna, gender);
    $('#' + gender).addClass('breedSelect')
    $('#' + gender).attr('data-catid', id)
    $('#' + gender).attr('onclick', 'breedKitties("' + gender + '")')
    $('#catDNA' + gender).html(`
    <span class="badge badge-light"><h4 class="tsp-2 m-0"><b>GEN:</b>`+ gen + `</h4><input class="hidden" id="` + gender + `Id" type="number" value=` + id + `></span>
    <br>
    <span class="badge badge-light"><h4 class="tsp-2 m-0"><b>DNA:</b>`+ dna + `</h4></span>`)
    $('#catSelection').modal('hide')
    removeSelection(id, gender)
    readyToBreed()

}

function readyToBreed() {

    var mumId = $('#female').val()
    var dadId = $('#male').val()

    if (!empty(mumId) && !empty(dadId)) {
        $('#breed').css('filter', 'none')
        $('#breed').prop('disabled', false)
        $('#breed').attr('onclick', 'breed(" ' + dadId + ' "," ' + mumId + ' ")')
        return true
    }
    $('#breed').prop('disabled', true)
    $('#breed').css('filter', ' grayscale()')
    return false
}

function removeSelection(id, gender){
    var selectionDiv = `
                        <div align="center">
                                <div class="egg">
                                </div>
                                <h4>Select a cat as `+ gender + `</h4>
                            </div>
                        </div>
                        `

    if (gender == 'female') {
        var catData = $('#male').attr('data-catid')
        if (catData == id) {
            $('#male').attr('data-catid', 0)
            $('#male').attr('onclick', 'breedCats(this.id)')
            $('#male').html(selectionDiv)
            $('#male').removeClass('breedSelect')
            $('#catDNAMale').html('')
        }
    }
    if (gender == 'male') {
        var catData = $('#female').attr('data-catid')
        if (catData == id) {
            $('#female').attr('data-catid', 0)
            $('#female').attr('onclick', 'breedCats(this.id)')
            $('#female').html(selectionDiv)
            $('#female').removeClass('breedSelect')
            $('#catDNAFemale').html('')
        }
    }
}

async function singleCat(dna, id, gen) {

    var catDna = catDna(dna)
    //2 build the singleCat into HTML
    var body = catBody(id)
    var Cattributes = cattributes(id)
    $('#cattributes').html(Cattributes)
    $('#singleCat').html(body)
    //3 Render the cats CSS style depending on DNA string
    renderCat(catDna, id)
    $('#catDNA').html(`
    <span class="badge badge-light"><h4 class="tsp-2 m-0"><b>GEN:</b>`+ gen + `</h4></span>
    <br>
    <span class="badge badge-light"><h4 class="tsp-2 m-0"><b>DNA:</b>`+ dna + `</h4></span>`)
    
    await catOffer(id)
}

async function catOffer(id) {

    //Checking if this cat is for Sale
    var offer = await checkOffer(id)
    var seller = offer.seller.toLocaleLowerCase()
    if (offer.onsale == true && seller != user) {
        $('#buyBox').removeClass('hidden')
        $('#priceBtn').html('<b>' + offer.price + ' ETH</b>')
        $('#buyBtn').attr('onclick', 'buyCat(' + id + ',"' + offer.price + '")')
    }
    
    var ownership = await catOwnership(id)
    //If user owns the cat
    if (ownership == true) {        
        //If is not on sale
        if (offer.onsale == false) {
            $('#sellBox').removeClass('hidden')
            $('#sellBtn').attr('onclick', 'sellCat(' + id + ')')
        } else {
            $('#sellBox').removeClass('hidden')
            $('#cancelBox').removeClass('hidden')
            $('#cancelBtn').attr('onclick', 'deleteOffer(' + id + ')')
            $('#sellBtn').addClass('btn-success')
            $('#sellBtn').html('<b>For sale at:</b>')
            $('#catPrice').val(offer.price)
            $('#catPrice').prop('readonly', true)
        }
    }
}

function renderCat(dna, id) {

    bodyColor(dna.headBodyColor, id)
    eyeColor(dna.eyesColor, id)
    bellyColor(dna.bellyMouthColor, id)
    earColor(dna.earsInnerTailColor, id)
    tailColor(dna.tailColor, id)
    
    eyeVariation(dna.eyesShape, id)
    decorationVariation(dna.decorationPattern, id)
    decorationMidColor(dna.decorationMidcolor, id)
    decorationSidesColor(dna.decorationSidescolor, id)
    animationVariation(dna.animation, id)
}


function catDNA(dnaAttribute){
    var dna = {
        //colors
        "headBodyColor": dnaAttribute.substring(0, 2),
        "eyesColor": dnaAttribute.substring(2, 4),
        "bellyMouthColor": dnaAttribute.substring(4, 6),
        "earsInnerTailColor": dnaAttribute.substring(6, 8),
        "tailColor": dnaAttribute.substring(8, 10),
        // cattributes
        "eyesShape": dnaAttribute.substring(10, 11),
        "decorationPattern": dnaAttribute.substring(11, 12),
        "decorationMidcolor": dnaAttribute.substring(12, 14),
        "decorationSidescolor": dnaAttribute.substring(14, 16),
        "animation": dnaAttribute.substring(16, 17),
        "lastNum": dnaAttribute.substring(17, 18)
    }
    console.log(dna);
    return dna;
}

function catContainer(id){
    var catDiv = `<div class="col-lg-4 pointer fit-content" id="catview` + id + `">
                 <div class="featureBox catDiv">
                 `+ catBody(id) + `                           
                 </div>
                 <div class="dnaDiv" id="catDNA`+ id + `"></div>
                 `+ cattributes(id) + `
                </div>`
    var catView = $('#catview' + id)
    if (!catView.length) {
        $('#catsDiv').append(catDiv)
    }
}

function catBody(id){
    var single = `  <div class = "cat" id = "newCat`+id+`">
                        <div id = "catEars" class =" ` + (animDna == 2 ? 'noddinghead' : 'ears') + `">
                            <div id = "leftEar `+ id + `" class= "ear left-ear">
                                <div class = " left-inner-ear"></div>
                            </div>
                            <div id = "rightEar `+ id + `" class = "ear right-ear">
                                <div class = "right-inner-ear"></div>
                            </div>
                        </div>

                        <div id = "catTail `+ id + `" class = "tail">
                            <div id = "inner-tail`+id+`"></div>
                        </div>

                        <div id = "catBody `+ id + `" class = "body"></div>
                        <div id = "catBelly `+ id + `" class = "belly"></div>
                        <div id = "catHead `+ id + `" class = "head">
                            <!-- <div class= "head-pattern"></div> -->
                                            <div id="midShape `+ id + `" class="head-shapes">
                                                <div id="leftShape `+ id + `" class="left_head-shape"></div>
                                                <div id="rightShape `+ id + `" class="right_head-shape"></div>
                                            </div>

                            <div id = "catEyes `+ id + `" class = "eyes">
                                <div class = "eye-left">
                                    <span id = "leftPupil `+ id + `" class = "pupil-left">
                                        <div class = "inner-eyes-big-left"></div>
                                        <div class = "inner-eyes-small-left"></div>
                                    </span>
                                </div>

                                <div class = "eye-right">
                                    <span id = "rightPupil `+ id + `" class = "pupil-right">
                                        <div class = "inner-eyes-big-right"></div>
                                        <div class = "inner-eyes-small-right"></div>
                                    </span>
                                </div>    
                            </div>


                            <div id = "mouth `+ id + `"></div>
                            <div class = "whiskers">
                                <div id = "rightWhiskers `+ id + `" class = "whiskers-right">
                                    <div class = "whisker1"></div>
                                    <div class = "whisker2"></div>
                                    <div class = "whisker3"></div>
                                </div>
                                <div id = "leftWhiskers `+ id + `" class = "whiskers-left">
                                    <div class = "whisker4"></div>
                                    <div class = "whisker5"></div>
                                    <div class = "whisker6"></div>
                                </div>
                            </div>
                            <div class = "mouth-left"></div>
                            <div class = "mouth-right"></div>
                            <div class = "nose"></div>
                            <div class = "chin"></div>
                        </div>


                        <div id = "bothFeet `+ id + `" class = "feet">
                            <div class = "foot-left"></div>
                            <div class = "foot-right"></div>
                        </div>
                    </div>`
    return single;
}


function cattributes(id) {

    var Cattributes = `<ul class="ml-5 cattributes">
                            <li>eyes: <span id="eyeName`+ id + `"></span></li>
                            <li>decoration: <span id="decorationName`+ id + `"></span></li>
                            <li>animation: <span id="animationName`+ id + `"></span></li>
                        </ul>`
    return Cattributes
}





buildCats.js

var colors = Object.values(allColors());

function bodyColor(code, id) {
    var color = colors[code];
    $('#catBody'+ id + ', #catHead'+ id +', #bothFeet'+ id).css('background', '#' + color)  //This changes the color of the cat
}

function eyeColor(code, id) {
    var color = colors[code];
    $('#catEyes'+ id).find('span').css('background', '#' + color);
    
}

function bellyColor(code, id) {
    var color = colors[code];
    $('#mouth'+ id +  ', #catBelly'+ id).css('background', '#' + color);
    
}

function earColor(code, id) {
    var color = colors[code];
    $('#leftEar'+ id + ', #rightEar' + id + ', #inner-tail'+ id).css('background', '#' + color);
    
}

function tailColor(code, id) {
    var color = colors[code];
    $('#catTail'+ id).css('background', '#' + color);
    
}
function decorationMidColor(code, id) {
    var color = colors[code];
    $('#midShape'+ id).css('background', '#' + color)  //This changes the mid decoration color of the cat
    
}

function decorationSidesColor(code, id) {
    var color = colors[code];
    $('#leftShape'+ id +  ', #rightShape'+ id).css('background', '#' + color)  //This changes the side decoration color of the cat
   
}



function eyeVariation(num, id) {

    switch (num) {
        case "1":
            normalEyes(id)//reset to default
            $('#eyeName'+id).html('Basic')//set the badge "Basic"
            break 
        case "2": 
            normalEyes(id)
            $('#eyeName'+id).html('Chiller')
            eyesType1(id)
            break
        case "3": 
            normalEyes(id)
            $('#eyeName'+id).html('Welling Up')
            eyesType2(id)
            break
        case "4":
            normalEyes(id)
            $('#eyeName'+id).html('Down Left')
            eyesType3(id)
            break
        case "5":
            normalEyes(id)
            $('#eyeName'+id).html('Down Right')
            eyesType4(id)
            break
        case "6": 
            normalEyes(id)
            $('#eyeName'+id).html('Sleepy')
            eyesType5(id)
            break
        case "7": 
            normalEyes(id)
            $('#eyeName'+id).html('Sour (left)')
            eyesType6(id)
            break
        case "8":
            normalEyes(id)
            $('#eyeName'+id).html('Sour (right)')
            eyesType7(id)
            break
        case "9": 
            normalEyes(id)
            $('#eyeName'+id).html('Cross-Eyed')
            eyesType8(id)
            break
        case "10":
            normalEyes(id)
            $('#eyeName'+id).html('Wink')
            eyesType9(id)
            break
        case "11":
            normalEyes(id)
            $('#eyeName'+id).html('Focus')
            eyesType10(id)
            break
    }
}

function decorationVariation(num, id) {
    
    switch (num) {
        case "1":
            $('#patternName'+id).html('Basic')
            normaldecoration(id)
            break
        case "2":
            normaldecoration(id)
            $('#patternName'+id).html('Spread')
            headPattern1(id)
            break
        case "3":
            normaldecoration(id)
            $('#patternName'+id).html('Long and Wide')
            headPattern2(id)
            break
        case "4":
            normaldecoration(id)
            $('#patternName'+id).html('Tiny')
            headPattern3(id)
            break
        case "5":
            normaldecoration(id)
            $('#patternName'+id).html('Upside Down')
            headPattern4()
            break
        
        case "6":
            normaldecoration(id)
            $('#patternName'+id).html('Fringe')
            headPattern5(id)
            break

        case "7":
            normaldecoration(id)
            $('#patternName'+id).html('Specks')
            headPattern6(id)
            break
    }
}

function animationVariation(num, id){
    
    switch (num){
        case 1: 
            noAnimation(id)
            $('#animationName'+id).html('Still')
            break
        case 2:
            noAnimation(id)
            $('#animationName'+id).html('Head and Ears Weave')
            animationType1(id)
            break
        case 3:
            noAnimation(id)
            $('#animationName'+id).html('Ears Move')
            animationType2(id)
            break
        case 4:
            noAnimation(id)
            $('#animationName'+id).html('Tail Moves')
            animationType3(id)
            break
        case 5:
            noAnimation(id)
            $('#animationName'+id).html('Eyes ')
            animationType4(id)
            break
        case 6:
            noAnimation(id)
            $('#animationName'+id).html('Whiskers Twitch')
            animationType5(id)
            break
        case 7:
            noAnimation(id)
            $('#animationName'+id).html('Blown Up')
            animationType6(id)
            break
        case 8:
            noAnimation(id)
            $('#animationName'+id).html('Dozing Off')
            animationType7(id)
            break
        case 9:
            noAnimation(id)
            $('#animationName'+id).html('Trip')
            animationType8(id)
            break

    }
}

//**********EYE TYPES************

var innerSmallLeft = document.getElementsByClassName('inner-eyes-small-left' )
var innerBigLeft = document.getElementsByClassName('inner-eyes-big-left')
var innerSmallRight = document.getElementsByClassName('inner-eyes-small-right')
var innerBigRight = document.getElementsByClassName('inner-eyes-big-right')
var leftPupil = document.getElementsByClassName('pupil-left')
var rightPupil = document.getElementsByClassName('pupil-right')

async function normalEyes(id) {
    await $('#catEyes'+id).find('span').css('border', 'none')
    await $('#catEyes'+id).find(innerBigLeft).css('background-color', 'blanchedalmond')
    await $('#catEyes'+id).find(innerBigRight).css('background-color', 'blanchedalmond')
    await $('#catEyes'+id).find(innerSmallLeft).css('background-color', 'blanchedalmond')
    await $('#catEyes'+id).find(innerSmallRight).css('background-color', 'blanchedalmond')
}
async function eyesType1(id) {//top lids half shut-- chiller
    await $('#catEyes'+id).find('span').css('border-top', '13px solid')
}
async function eyesType2(id) {//bottom lids half shut-- welling up
    await $('#catEyes'+id).find('span').css('border-bottom', '13px solid')
}
async function eyesType3(id) {//looking down left
    await $('#catEyes'+id).find('span').css('border-top', '12px solid')
    await $('#catEyes'+id).find('span').css('border-right', '12px solid')

}
async function eyesType4(id) {//looking down right
    await $('#catEyes'+id).find('span').css('border-top', '12px solid')
    await $('#catEyes'+id).find('span').css( 'border-left', '12px solid')
}

async function eyesType5(id) {//sleepy
    await $('#catEyes'+id).find('span').css('border-top', '17px solid')
    await $('#catEyes'+id).find('span').css('border-bottom', '10px solid')
    await $('#catEyes'+id).find(innerBigRight).css('background-color', '#ffebcd00')
    await $('#catEyes'+id).find(innerSmallLeft).css('background-color', '#ffebcd00')
    await $('#catEyes'+id).find(innerSmallRight).css('background-color', '#ffebcd00')
    await $('#catEyes'+id).find(innerBigLeft).css('background-color', '#ffebcd00')
}

async function eyesType6(id) {//top lid half shut left eye
    await $('#catEyes'+id).find(leftPupil).css('border-top', '13px solid')
}
async function eyesType7(id) {//top lid half shut right eye
    await $('#catEyes'+id).find(rightPupil).css('border-top', '13px solid')
}

async function eyesType8(id) {//cross-eyed
    await $('#catEyes'+id).find(leftPupil).css('border-left', '11px solid')
    await $('#catEyes'+id).find(rightPupil).css('border-right', '12px solid')
}

async function eyesType9(id) { //wink left eye
    await $('#catEyes'+id).find(leftPupil).css('border-top', '14px solid')
    await $('#catEyes'+id).find(leftPupil).css('border-bottom', '15px solid')
    await $('#catEyes'+id).find(innerBigLeft).css('background-color', '#ffebcd00')
    await $('#catEyes'+id).find(innerSmallLeft).css('background-color', '#ffebcd00')
}

async function eyesType10(id) {//small pupil
    await $('#catEyes'+id).find('span').css('border-top', 'solid 7px')
    await $('#catEyes'+id).find('span').css('border-bottom', 'solid 7px')
    await $('#catEyes'+id).find('span').css('border-left', 'solid 7px')
    await $('#catEyes'+id).find('span').css('border-right', 'solid 7px')
}

//********** HEAD PATTERNS **********


async function normaldecoration(id) {
    //Remove all style from other decorations
    //In this way we can also use normalDecoration() to reset the decoration style
    $('#midShapes'+id).css({ "transform": "rotate(0deg)", "height": "48px", "width": "14px", "top": "1px", "left": "92px", "border-radius": "0 0 50% 50%" })
    $('#leftShape'+id).css({ "transform": "rotate(0deg)", "height": "35px", "width": "14px", "top": "0px", "left": "-13px", "border-radius": "50% 0 50% 50%" })
    $('#rightShape'+id).css({ "transform": "rotate(0deg)", "height": "35px", "width": "14px", "top": "0px", "left": "13px", "border-radius": "0 50% 50% 50%" })
}

async function headPattern1(id){
    $('#midShapes'+id).css({ "top": "3px", "border-radius": "30% 30% 50% 50%"})
    $('#leftShape'+id).css({ "transform": "rotate(63deg)", "height": "35px", "width": "14px", "top": "-3px", "border-radius": "50% 0 50% 50%" })
    $('#rightShape'+id).css({ "transform": "rotate(-63deg)", "height": "35px", "width": "14px", "top": "-2px", "border-radius": "50% 0 50% 50%" })

}

 async function headPattern2(id) {
     await $('#midShapes'+id).css({ "top": "3px", "border-radius": "30% 30% 50% 50%"})
     await $('#leftShape'+id).css({ "transform": "rotate(72deg)", "height": "63px", "width": "14px", "top": "-19px", "left": "-27px", "border-radius": "50% 0 50% 50%" })
     await $('#rightShape'+id).css({ "transform": "rotate(-74deg)", "height": "63px", "width": "14px", "top": "-17px", "left": "27px", "border-radius": "50% 0 50% 50%" })
 }
 
 async function headPattern3(id) {
     await $('#midShapes'+id).css({ "top": "4px", "border-radius": "30% 30% 50% 50%"})
     await $('#leftShape'+id).css({ "transform": "rotate(30deg)", "height": "35px", "width": "14px", "top": "1px", "border-radius": "50% 0 50% 50%" })
     await $('#rightShape'+id).css({ "transform": "rotate(-30deg)", "height": "35px", "width": "14px", "top": "1px", "border-radius": "50% 0 50% 50%" })
 
     await $('#midShapes'+id).css({ "transform": "scale(0.3)"})
     await $('#midShapes'+id).css({ "top": "-5"})
   }
 
   async function headPattern4(id) {
     await $('#midShapes'+id).css({ "top": "4px", "border-radius": "30% 30% 50% 50%"})
     await $('#leftShape'+id).css({ "transform": "rotate(25deg)", "height": "38px", "width": "14px", "top": "-2px", "left": "-8px" })
     await $('.#leftShape'+id).css({ "transform": "rotate(-30deg)", "height": "35px", "width": "14px", "top": "0px", "left": "9px" })
     await $('#midShapes'+id).css({ "transform": "rotate(180deg)"})
     await $('#midShapes'+id).css({ "top": "4px"})   
   }
 
   async function headPattern5(id) {   
     await $('#leftShape'+id).css({"height": "60px", "width": "15px"})
     await $('#rightShape'+id).css({"height": "60px", "width": "15px", "top": "0px"})   
   }
 
   async function headPattern6(id) {   
     await $('#midShapes'+id).css({ "height": "10px", "width": "5px", "transform": "rotate(-1deg)", "left": "97px"})
     await $('#leftShape'+id).css({"height": "10px", "width": "5px"})
     await $('#rightShape'+id).css({"height": "10px", "width": "5px"})   
   }
 

//*********ANIMATIONS**********

function noAnimation(id){
    document.getElementById('catHead'+id).classList.remove('noddingHead','movingHead')
    document.getElementById('catEars'+id).classList.remove('noddingHead')
    document.getElementById('leftEar'+id).classList.remove('movingLeftEar')
    document.getElementById('rightEar'+id).classList.remove('movingRightEar')
    document.getElementById('catTail'+id).classList.remove('movingTail')
    document.getElementById('rightWhiskers'+id).classList.remove('movingWhiskersRight')
    document.getElementById('leftWhiskers'+id).classList.remove('movingWhiskersLeft')
    document.getElementById('catBody'+id).classList.remove('enflatedBelly')
    document.getElementById('catBelly'+id).classList.remove('enflatedBelly')
    document.getElementById('leftPupil'+id).classList.remove('eyesTired', 'eyesChangeColor')
    document.getElementById('rightPupil'+id).classList.remove('eyesTired', 'eyesChangeColor')
    document.getElementById('catEyes'+id).classList.remove('eyesBigger')
    document.getElementById('bothFeet'+id).classList.remove('enflatedFeet')

}

async function animationType1(id){//head and ears weave side to side
    $('#catHead'+id).addClass('noddingHead')
    $('#catEars'+id).addClass('noddingHead')
}

async function animationType2(id){ //ears move
    $('#leftEar'+id).addClass('movingLeftEar')
    $('#rightEar'+id).addClass('movingRightEar')
}

async function animationType3(id){
    $('#catTail'+id).addClass('movingTail')
}

async function animationType4(id){ //bigger eyes
    $('#catEyes'+id).addClass('eyesBigger')
    
}

async function animationType5(id){ //whiskers move
    $('#rightWhiskers'+id).addClass('movingWhiskersRight')
    $('#leftWhiskers'+id).addClass('movingWhiskersLeft')

}

async function animationType6(id){ //fat
    $('#catBody'+id).addClass('enflatedBelly')
    $('#catBelly'+id).addClass('enflatedBelly')
    $('#bothFeet'+id).addClass('enflatedFeet')
}

async function animationType7(id){
    $('#leftPupil'+id).addClass('eyesTired')
    $('#rightPupil'+id).addClass('eyesTired')
}

async function animationType8(id){// mutli-coloured eyes
    $('#leftPupil'+id).addClass('eyesChangeColor')
    $('#rightPupil'+id).addClass('eyesChangeColor')
}






//eyes following cursor
const closer = 4;
const further = -4;

document.addEventListener('mousemove', (e) => {
    let positionX = e.pageX;
    let positionY = e.pageY;

    let width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    let height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

    let moveX = (positionX - width) / (width) * closer;
    let moveY = (positionY - height) / (height) * closer;

    $('.pupil-left').css('transform', 'translate(' + moveX + 'px,' + moveY + 'px)')
    $('.pupil-right').css('transform', 'translate(' + moveX + 'px,' + moveY + 'px)')

}, false);





catalogue.html
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="shortcut icon" href="./image/circle-croppedfinal.png" type="image/x-icon">
  <title>Crypto Cats</title>
  <script type="text/javascript" src="assets/js/jquery-3.4.1.js"></script>
  <link href="https://fonts.googleapis.com/css2?family=Dosis:wght@400&display=swap" rel="stylesheet">

  <link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
  <script src="assets/bootstrap/js/popper.js"></script>
  <script src="assets/bootstrap/js/bootstrap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.0.2/anime.min.js"></script>

  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
  <script src="./abi.js"></script>
  <script src="./index.js"></script>

  
  <link rel="stylesheet" href="assets/css/mystyle.css">
  <link rel="stylesheet" href="assets/css/colors.css">
  <link rel="stylesheet" href="assets/css/factory.css">
  <link rel="stylesheet" href="assets/css/frontend.css">
  <link rel="stylesheet" href="assets/css/animations.css">
  <link rel="stylesheet" href="assets/css/cats.css">
  <link rel="stylesheet" href="assets/css/catalogue.css">
  <script src="https://kit.fontawesome.com/8d9e2e73ef.js" crossorigin="anonymous"></script>

  <style>
    body{
        background: rgb(144,197,188);
    }
    </style>
</head>
  <body>
    
    <div id = "menuBar"></div>

    <div class="container p-5 header">
        <div align="center">
        <h1><i class="fas fa-cat" ></i>  Cat Litter  <i class="fas fa-cat" style="transform: scaleX(-1)"></i></h1>
        <p>All Your Cats Mingle Here </p>
    </div>

    <div class="container middleBox">
      <span class="row" id="catsDiv">

      </span>

      <div class="row" id="ownersCatsDiv hidden">

      </div>


  </div>

        <form method = "get" action="./breed.html">
          <button type = "submit" class = "btn btn-warning">Breed Your Cats</button>
        </form>
        <br>

        <div class="row">

        </div>

    </div>
  
    <footer align="left">
        <p>Crypto Cats, Ollie Francis 2021</p>
    </footer>

  </body>

    <footer align="left">
        <p>Ivan on Tech Academy April 2021</p>
    </footer>

  </body>
  <script src="assets/js/colors.js"></script>
  <script src="./assets/js/buildCat.js"></script>
  <script src="./assets/js/showCat.js"></script>
  <script src="assets/js/catFactory.js"></script>
  <script src="menu.js"></script>


</html>

Github repo: https://github.com/olfrank/Crypto_Cats_Dapp

Thanks fellas.
Screenshot 2021-08-10 at 12.14.42

Ok @ol_frank I took a look to your code.
So first thing you can do for having the cat inside the box, is to give a min-height property to the cat box container. Now its showing at botton because elements inside dont have enough height. So this can be fix just min-height depending on your cats, you can test this in console.

Regarding the colors, it is because you have to render styles for each cat, try with 2 first the you can do it with more. The functions that are applying styles and colors, should select the correct box for each cat.

I AM A MUPPET!!!

Managed to fix the issue. It turns out i had a space in-between the id name and the + id bit in the catBody function.

Like this:

<div id = "rightEar  `+ id + `" class = "ear right-ear">
 I had a space here ^ 
When there shouldn't have been 
<div id = "rightEar`+ id + `" class = "ear right-ear">
                                

Its always the tiny typo’s that ruin my day haha. Got to make mistakes to learn from them i guess.
Thank you for looking into my issue @kenn.eth

2 Likes

Great @ol_frank well done! Functions looks all correct. Typo’s in this project are difficult to take in count because there is a lot of parts. But also a good practice to check everything carefully.

2 Likes

Im after a little help with my catContract. I realised that for a few function calls i was trying to fix the error below by just adding this. in front of the call but its completely incorrect and is causing issues.

To make this issue clearer to understand my original syntax was:
this.balanceOf(_owner)
When it should be
balanceOf(_owner)
However the error below pops up.


Undeclared identifier. “balanceOf” is not (or not yet) visible at this point.


Screenshot 2021-08-17 at 12.48.16

So as you can see i have multiple errors saying Undeclared Identifier. I am clueless as to why they are not yet visible and how to fix this.

Here is my contract. Maybe someone can help me with this??? Thanks
@kenn.eth @thecil

pragma solidity >=0.4.22 <0.9.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "../node_modules/@openzeppelin/contracts/access/Ownable.sol";
contract Catcontract is IERC721 {

string private  constant Name = "Purrfect";
string private constant Symbol = "PURR";
uint16 private constant Gen0_Creation_Limit = 10;
bytes4 internal constant MAGIC_ERC721_RECEIVED= bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
address public contractOwner;

event Birth(address owner, uint256 catId, uint256 mumId, uint256 dadId, uint256 genes);


modifier onlyOwner{
    require(contractOwner == msg.sender, "You are not the owner of the contract");
    _;
}

struct Cat {
    uint256 genes;
    uint64 birthTime;
    uint32 mumId;
    uint32 dadId;
    uint16 generation;
}

constructor(){
    contractOwner = msg.sender;
    uint256 gen = type(uint256).max;
    _createCat(0, 0, 0, gen, address(0));//_createCat(0, 0, 0, gen-1, address(0))
}

Cat[] cats;
//        owner => amount
mapping(address => uint256) ownerTokenBalance;

//      tokenId => owner of cat
mapping(uint256 => address) public catIndexToOwner;

// tokenId => another approved address 
mapping(uint256 => address) public catIndexToApproved;

mapping(address => mapping(address => bool)) private operatorApprovals;

uint256 public gen0Counter;



function breed(uint256 _dadId, uint256 _mumId) public {
    //check ownership
    //check you got the dna
    //figure out the generation
    //create a new cat with new properties, give it to msg.sender
    require(owns(msg.sender, _dadId) && owns(msg.sender, _mumId), "You must own both cats in order to breed");
    require(_mumId != _dadId, "The cat can't breed itself");
    uint256 newCatDna = mixDna(_dadId, _mumId);
    
    uint256 newGen; 
    uint256 mumGen = cats[_mumId].generation;
    uint256 dadGen = cats[_dadId].generation;

    if(dadGen == mumGen){
        newGen = mumGen++;
    }else if(dadGen < mumGen){
        newGen = dadGen++;
    }else{
        newGen = (dadGen + mumGen) / 2;
    }
    
    _createCat(newCatDna, _mumId, _dadId, newGen, msg.sender);
}

function mixDna(uint256 _dadDNA, uint256 _mumDNA) internal view returns(uint256){
    uint256[9] memory geneArray;
    //sudo random number
    uint16 random = uint16(block.timestamp)%511; //binary between 000000000-111111111
    
    uint256 index = 8;
    for(uint8 i = 0; i <= 256; i=i*2){ //1, 2, 4, 8, 16, 32, 64, 128, 256 = 9 pairs
        if(random & i != 0){
            geneArray[index] = uint16( _mumDNA % 100);
        }else{
            geneArray[index] = uint16( _dadDNA % 100);
        }
            _mumDNA = _mumDNA / 100;//removing the last two digits by moving the decimal point
            _dadDNA = _dadDNA / 100;
            index = index -1; 
    }
    uint256 newGene;
    for(uint8 i = 0; i < 9; i++){
        newGene = newGene + geneArray[i];
        if(i != 8){
            newGene = newGene *100;
        }
    }
    return newGene;

}

function createCatGen0(uint256 _genes)public onlyOwner{
    require(gen0Counter < Gen0_Creation_Limit, "gen0Counter < Gen0_Creation_Limit");
    gen0Counter++;

    _createCat(_genes, 0, 0, 0, msg.sender);
}

function _createCat(
    uint256 _genes,
    uint256 _mumId,
    uint256 _dadId,
    uint256 _generation,
    address _owner
)internal returns(uint256){
    Cat memory _cat = Cat({
        genes: uint256(_genes),
        birthTime: uint64(block.timestamp),
        mumId: uint32(_mumId),
        dadId: uint32(_dadId),
        generation: uint16(_generation)
    });

    //uint256 newCatId = cats.push(_cat)-1;
    cats.push(_cat);
    uint256 newCatId = cats.length - 1;
     

    emit Birth(_owner, newCatId, _mumId, _dadId, _genes);

    _transfer(address(0), _owner, newCatId);

    return newCatId;
}

    //returning the values in uint256 due to front end preferences (easier to read)
    function getCat(uint256 _tokenId) public view returns(
        uint256 genes, 
        uint256 birthTime, 
        uint256 mumId, 
        uint256 dadId, 
        uint256 generation, 
        address owner 
        ){
        return(
            genes = cats[_tokenId].genes,
            birthTime = cats[_tokenId].birthTime,
            mumId = cats[_tokenId].mumId,
            dadId = cats[_tokenId].dadId,
            generation = cats[_tokenId].generation,
            owner = catIndexToOwner[_tokenId]
        );
    }

    function supportsInterface(bytes4 _interfaceId) external pure returns (bool){
        return(_interfaceId ==_INTERFACE_ID_ERC721 || _interfaceId == _INTERFACE_ID_ERC165);
    }

    function balanceOf(address owner) external view override returns (uint256 balance){
        balance = ownerTokenBalance[owner];
        return balance;
    }

    function totalSupply() external view override returns (uint256 total){
        total = cats.length;
        return total; 
    }

    function ownerOf(uint256 tokenId) external view override returns (address owner){
        return catIndexToOwner[tokenId];
    }


    function transfer(address to, uint256 tokenId) external override{
        require(to != address(0), "Cannot Send Tokens To This Address");
        require(to != address(this), "Cannot Send Tokens To This Address");
        require(owns(msg.sender, tokenId), "You Must Own The Token You Are Sending");
        _transfer(msg.sender, to, tokenId);
    }

    function _transfer(address from, address _to, uint256 _tokenId) internal {
        ownerTokenBalance[_to]++;
        catIndexToOwner[_tokenId] = _to;

        //(edge case senario) when we mint new cats we dont want to decrease the token count
        if(from != address (0)) {
            ownerTokenBalance[from]--;
            //this makes sure that the approval history for that token is erased
            delete catIndexToApproved[_tokenId];
        }
        emit Transfer(from, _to, _tokenId);
    }

    function owns(address claimant, uint256 _tokenId) internal view returns (bool){
        return catIndexToOwner[_tokenId] == claimant;
    }

    function approve(address to, uint256 _tokenId) external override {
        require(owns(msg.sender, _tokenId));
        _approve(to, _tokenId);
        emit Approval(msg.sender, to, _tokenId);
    }

    function _approve(address approved, uint256 tokenId) internal {
        catIndexToApproved[tokenId] = approved;
    }

    function setApprovalForAll(address operator, bool approved) external override{ 
        require(operator != msg.sender);
        _setApprovalForAll(operator, approved);
        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function _setApprovalForAll(address _operator, bool _approved) internal{
        operatorApprovals[msg.sender][_operator] = _approved;
    }

    function getApproved(uint256 _tokenId) external view override returns (address){
        require(_tokenId < cats.length);//check that the token exists
        return catIndexToApproved[_tokenId];
    }

    function isApprovedForAll(address _owner, address _operator) external override view returns (bool){
        //returns the mapping status for these inputs
        return operatorApprovals[_owner][_operator];
    } 
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external override{
        _safeTransfer(_from, _to, _tokenId, "");
    }

    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external override{
        require(ownerOrApprovedCheck(msg.sender, _from, _to, _tokenId));
        _safeTransfer(_from, _to, _tokenId, data);
    }

    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data)internal {
        _transfer(from, to, tokenId);
        require(_checkERC721Support(from, to, tokenId, data));
    }

    function transferFrom(address _from, address _to, uint256 _tokenId) external override{
        require(ownerOrApprovedCheck(msg.sender, _from, _to, _tokenId));
        _transfer(_from, _to, _tokenId);
    }

    function _checkERC721Support(address from, address to, uint256 tokenId, bytes memory data) internal returns(bool){
        if( !isContract(to) ){
            return true; //if it is not a contract return true
        }
        //call onERC721Recieved in the to contract
        bytes4 returnData = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, data);
        return returnData == MAGIC_ERC721_RECEIVED;
    }

    function isContract(address _to) internal view returns(bool){
        uint32 size;
        assembly{
            size := extcodesize(_to)
        }

        return size > 0;
    }

    function approvedFor(address claimant, uint256 tokenId) internal view returns(bool){
        return catIndexToApproved[tokenId] == claimant;
    }

    function name() external pure override returns (string memory tokenName){    return Name;    }
    function symbol() external pure override returns (string memory tokenSymbol){    return Symbol;  }

    //to reduce code duplication, made an internal function with the require statements and returns true/false
    function ownerOrApprovedCheck(address spender, address _from, address _to, uint256 _tokenId) internal view returns(bool){
        require(owns(_from, _tokenId));
        require(_to != address(0));
        require(_tokenId < cats.length);
        return(spender == _from || approvedFor(spender, _tokenId) || isApprovedForAll(_from, spender));

    }

    function ownedTokens(address _owner) public view returns(uint256[] memory ownerTokens) {
    uint256 tokenCount = balanceOf(_owner);

    if (tokenCount == 0) {
        return new uint256[](0);
    } else {
        uint256[] memory result = new uint256[](tokenCount);
        uint256 totalCats = totalSupply();
        uint256 resultIndex = 0;

        uint256 catId;

        for (catId = 1; catId <= totalCats; catId++) {
            if (catIndexToOwner[catId] == _owner) {
                result[resultIndex] = catId;
                resultIndex++;
            }
        }

        return result;
    }
    
    }
}
1 Like

Hey @ol_frank, hope you are well.

The problem comes from a visibility level in those functions, you have set them as external so their only visible for external contracts, if you change them to public, their should be visible to the contract.

Carlos Z

2 Likes

Hi all!

Can somebody look at my code?

Once I create a kitty it’s not adding to the catalouge part but console does not come up with any error either?

My link to my repo : https://github.com/Riki0923/CryptoKitties

Thank you very much.

Riki

Hi All!

Were somebody were able too look at the above?

Riki

hey @Riki ! Are you able to print this part of the cat ?
for(let i = 0; i < allCatsId.length; i++){


        let kittenId = allCatsId[i];

        console.log("Current Kitten Id: " + kittenId);

        let object = await instance.methods.getKitty(allCatsId[i]).call();

        let catGenes = object.genes;

        console.log("Current genes: " + catGenes);

        let catBirthday = object.birthTime;

        console.log("Current Birthday: " + new Date(catBirthday * 1000));

        let catMumId = object.mumId;

        console.log("Current MumId: " + catMumId);

        let catDadId = object.dadId;

        console.log("Current DadId: " + catDadId);

        let catGeneration = object.generation;

        console.log("Current Generation: " + catGeneration);

        createCatBox(kittenId, catGenes);

    }

This is after console.log("CATS COUNT: " + catsCount);

Hey @kenn.eth!

No, unfortunately not, only the cats count is printed into the console.

hey @Riki I just checkout your code and find the isssue is in the _own function wich should return a bool after your require but is not returning anything.

Instead of require, we can simply use an if coditional statement, and return just true in case the mapping match with the owner like this :

// Line 156 Kittycontract.sol
    function _own(address _claimant, uint256 _tokenId) public view returns(bool){
        if(ownerOfToken[_tokenId] == _claimant) return true;
    }

Hopes it help. Let me know if you solve it.

1 Like

Yes it did! Tried out so many things but this did not came to my mind of course…

Now I am getting this if I create a Cat. I am looking on it now what can be the issue but probably in the div part ( or not ) ?:

I have tried to do many things to change in the div part, but still the only thing I can change is that the DNA part appears or not, nothing else is coming up. Am I right to look on that part or is there something else to check?

You have to run the render function and console.log() each part that is not rendering in order to debug it. So you will find what is missing out part by part.

@kenn.eth

Okay I have done what you asked.

So you meant for the function in the CatSetting.js right?

I have console logged out every function and all dna.number which you can see on this picture:

Did you meant for this function? So here everything seems fine expect the dna which logs out as object Object.